W moim skrypcie próbuję sprawdzić błąd, czy pierwszy i jedyny argument jest równy -v, ale jest to argument opcjonalny. Używam instrukcji if, ale ciągle otrzymuję oczekiwany błąd operatora jednoargumentowego.
to jest kod:
if [ $1 != -v ]; then
echo "usage: $0 [-v]"
exit
fi
Edytować:
Powinienem być bardziej szczegółowy: ta część powyższego skryptu sprawdza opcjonalny argument, a następnie, jeśli argument nie zostanie wprowadzony, powinien uruchomić resztę programu.
#!/bin/bash
if [ "$#" -gt "1" ]; then
echo "usage: $0 [-v]"
exit
fi
if [ "$1" != -v ]; then
echo "usage: $0 [-v]"
exit
fi
if [ "$1" = -v ]; then
echo "`ps -ef | grep -v '\['`"
else
echo "`ps -ef | grep '\[' | grep root`"
fi
echo "usage: $0 [-v]"
;$-
pokazuje flagi opcji aktywnej powłoki, a nie nazwę bieżącego skryptu.$-
jest nazwą bieżącego skryptu. jest.$0
Odpowiedzi:
Cytaty!
if [ "$1" != -v ]; then
W przeciwnym razie, gdy
$1
jest całkowicie pusty, test wygląda następująco:zamiast
[ "" != -v ]
... i
!=
nie jest operatorem jednoargumentowym (czyli takim, który może przyjąć tylko jeden argument).źródło
if [[ $1 != -v ]]; then
IFS=1
, to[ $# -eq 1 ]
nie będzie zachowywał się tak dobrze,[ "$#" -eq 1 ]
ale nawet wtedy zachowuje się zgodnie z zamierzeniami. To oczywiście patologiczny przypadek, ale lepiej jest pisać oprogramowanie, które ich nie ma, gdy ma się wybór.Lub z powodu czegoś, co wydaje się szalejącą przesadą, ale w rzeczywistości jest uproszczone ... Prawie obejmuje wszystkie twoje przypadki, bez pustych ciągów lub jednoargumentowych problemów.
W przypadku, gdy pierwszym argumentem jest „-v”, wykonaj warunek
ps -ef
, w przeciwnym razie we wszystkich innych przypadkach wyrzuć użycie.#!/bin/sh case $1 in '-v') if [ "$1" = -v ]; then echo "`ps -ef | grep -v '\['`" else echo "`ps -ef | grep '\[' | grep root`" fi;; *) echo "usage: $0 [-v]" exit 1;; #It is good practice to throw a code, hence allowing $? check esac
Jeśli nie obchodzi nas, gdzie jest argument „-v”, po prostu umieść wielkość liter w pętli. Pozwoliłoby przejść przez wszystkie argumenty i znaleźć „-v” w dowolnym miejscu (o ile istnieje). Oznacza to, że kolejność argumentów w wierszu poleceń nie jest ważna. Ostrzegam, jak przedstawiono, zmienna arg_match jest ustawiona, więc jest to tylko flaga. Pozwala na wielokrotne wystąpienie argumentu „-v”. Można łatwo zignorować wszystkie inne wystąpienia „-v”.
#!/bin/sh usage () { echo "usage: $0 [-v]" exit 1 } unset arg_match for arg in $* do case $arg in '-v') if [ "$arg" = -v ]; then echo "`ps -ef | grep -v '\['`" else echo "`ps -ef | grep '\[' | grep root`" fi arg_match=1;; # this is set, but could increment. *) ;; esac done if [ ! $arg_match ] then usage fi
Jednak zezwalanie na wiele wystąpień argumentu jest wygodne w użyciu w takich sytuacjach, jak:
Nie dbamy o kolejność argumentów, a nawet zezwalamy na wiele argumentów -u. Tak, łatwo jest również zezwolić na:
źródło
$*
nie powinno być używane w tym kontekście: Łączy elementy w łańcuch, który jest zarówno podzielony na łańcuchy, jak i rozszerzony globalnie; w odróżnieniu"$@"
, co pozostawia przedmioty z ich dokładnymi oryginalnymi wartościami. Brakuje niektórych cudzysłowów, które złapie shellcheck.net (z ostrzeżeniami połączonymi ze stroną wiki, która opisuje, dlaczego te cytaty były ważne).-U'Bob Barker'
;for arg in $*
będzie go zobaczyć jako-UBob
, a następnieBarker
jako osobna pozycja; podczas gdyfor item in "$@"
będzie-UBob Barker
to pojedynczy ciąg.