Poniższa składnia bash sprawdza, czy param
nie jest „t pusty”:
[[ ! -z $param ]]
Na przykład:
param="" [[ ! -z $param ]] && echo "I am not zero"
Brak wyjścia i wszystko w porządku.
Ale kiedy param
jest puste, z wyjątkiem jednego (lub więcej) znaków spacji, wtedy wielkość liter jest inna:
param=" " # one space [[ ! -z $param ]] && echo "I am not zero"
„Nie jestem zero ”.
Jak mogę zmienić test, aby uwzględniał zmienne zawierające tylko spacje jako puste?
Komentarze
- Z
man test
:-z STRING - the length of STRING is zero
. Jeśli chcesz usunąć wszystkie spacje w$param
, użyj${param// /}
- WOW nie ma prostej funkcji
trim()
wbudowanej w w ogóle jakieś * nix? Tak wiele różnych sposobów na osiągnięcie czegoś tak prostego … - @ADTC $ (sed ' s / ^ \ s + | \ s + $ // g ' < < < $ string) wydaje mi się dość proste. Po co odkrywać koło na nowo?
- Ponieważ mogłoby być bardziej błyszczące
- Wystarczy zauważyć, że
[[ ! -z $param ]]
jest równoważne ztest ! -z $param
.
Odpowiedź
Po pierwsze, zwróć uwagę, że -z
test jest wyraźnie przeznaczony dla:
długość łańcucha wynosi zero
Oznacza to, że ciąg zawierający tylko spacje powinien a nie będzie prawdziwe pod -z
, ponieważ ma niezerową długość.
To, czego chcesz, to usunięcie spacji ze zmiennej za pomocą rozwinięcie parametru zastępującego wzorzec :
[[ -z "${param// }" ]]
To rozszerza param
i zastępuje wszystkie dopasowania wzorca (pojedyncza spacja) niczym, więc ciąg zawierający tylko spacje zostanie rozwinięty do pusty ciąg.
najważniejsze, jak to działa , to ${var/pattern/string}
zamienia pierwsze najdłuższe dopasowanie pattern
na string
. Kiedy pattern
zaczyna się od /
(jak wyżej), zastępuje wszystkie dopasowania. Ponieważ zamiennik jest pusty, możemy pominąć ostatnią wartość /
i string
:
$ {parametr / wzorzec / ciąg}
wzorzec jest rozwijany w celu utworzenia wzorca, tak jak przy rozwijaniu nazw plików. Parametr jest rozwijany, a najdłuższe dopasowanie wzorca do jego wartości jest zastępowane ciągiem . Jeśli wzorzec zaczyna się od „/”, wszystkie dopasowania wzorca są zastępowane ciągiem . Zwykle zastępowane jest tylko pierwsze dopasowanie. … Jeśli ciąg ma wartość null, dopasowania wzorca są usuwane, a / następujący wzorzec może zostać pominięty.
Po tym wszystkim otrzymujemy ${param// }
, aby usunąć wszystkie spacje.
Pamiętaj, że obecny w ksh
(skąd pochodzi), zsh
i bash
, ta składnia nie jest POSIX i nie powinien być używany w sh
skryptach.
Komentarze
Odpowiedź
Prosty sposób sprawdzenie, czy ciąg zawiera tylko znaki z autoryzowanego zestawu, jest testem na obecność nieautoryzowanych znaków.Dlatego zamiast sprawdzać, czy ciąg zawiera tylko spacje, sprawdź, czy ciąg zawiera znak inny niż spacja. W bash, ksh lub zsh:
if [[ $param = *[!\ ]* ]]; then echo "\$param contains characters other than space" else echo "\$param consists of spaces only" fi
„Składa się tylko ze spacji” obejmuje przypadek pustej (lub nieustawionej) zmiennej.
Możesz chcieć sprawdzić, czy nie ma żadnych białych znaków. Użyj [[ $param = *[^[:space:]]* ]]
, aby użyć ustawień regionalnych lub dowolnej jawnej listy białych znaków, które chcesz przetestować, np. [[ $param = *[$" \t\n"]* ]]
do testowania spacji, tabulacji lub nowej linii.
Dopasowanie ciągu do wzorca z =
wewnątrz [[ … ]]
to rozszerzenie ksh (obecne także w bash i zsh). W każdym stylu Bourne / POSIX można użyć konstrukcji case
w celu dopasowania ciągu do wzorca. Zwróć uwagę, że standardowe wzorce powłoki używają !
do zanegowania zestawu znaków, a nie ^
, jak w większości składni wyrażeń regularnych.
case "$param" in *[!\ ]*) echo "\$param contains characters other than space";; *) echo "\$param consists of spaces only";; esac
Aby sprawdzić, czy nie ma białych znaków, składnia $"…"
jest specyficzna dla ksh / bash / zsh; możesz wstawić te znaki w swoim skrypcie dosłownie (pamiętaj, że znak nowej linii będzie musiał znajdować się w cudzysłowie, ponieważ ukośnik odwrotny + znak nowej linii oznacza nic) lub wygeneruj je, np.
whitespace=$(printf "\n\t ") case "$param" in *[!$whitespace]*) echo "\$param contains non-whitespace characters";; *) echo "\$param consists of whitespace only";; esac
Komentarze
- To jest prawie doskonałe – ale jak dotąd nie odpowiada na zadane pytanie. Obecnie jest w stanie wskazać różnicę między nieustawioną lub pustą zmienną powłoki a taką, która zawiera tylko spacje. Jeśli zaakceptujesz moją sugestię, dodasz formularz rozwijania parametrów, który nie został jeszcze poznany przez żadną inną odpowiedź, która wyraźnie testuje zmienną powłoki pod kątem ustawienia – mam na myśli
${var?not set}
– zaliczenie tego testu i przetrwanie zapewni, że zmienna dopasowana do Twojego*)
case
wpłynie na przykład na ostateczną odpowiedź. - Poprawka – w rzeczywistości oznaczałoby odpowiedź na pierwotnie zadane pytanie, ale od tego czasu zostało zredagowane w taki sposób, że zasadniczo zmienia znaczenie pytania, a tym samym unieważnia twoją odpowiedź.
- Potrzebujesz
[[ $param = *[!\ ]* ]]
wmksh
.
Odpowiedź
POSIXly:
case $var in (*[![:blank:]]*) echo "$var contains non blank";; (*) echo "$var contains only blanks or is empty or unset" esac
Aby odróżnić puste , niepuste , pusty , nieustawiony :
case ${var+x$var} in (x) echo empty;; ("") echo unset;; (x*[![:blank:]]*) echo non-blank;; (*) echo blank esac
[:blank:]
służy do znaków odstępów poziomych (spacja i tabulator w A SCII, ale prawdopodobnie jest ich kilka więcej w twoim locale; niektóre systemy będą zawierać nierozdzielającą spację (jeśli jest dostępna), inne nie będą miały „t”. Jeśli chcesz, aby również znaki odstępów pionowych (np. nowa linia lub wysuw strony), zamień [:blank:]
z [:space:]
.
Komentarze
- POSIXly jest idealne, ponieważ będzie działać z (prawdopodobnie lepiej) myślnik.
-
zsh
wydaje się mieć problem z[![:blank:]]
, podnosi:b
jest nieprawidłowym modyfikatorem. W emulacjish
iksh
zgłasza zdarzenie nie znalezione dla[
- @cuonglm, czego próbowałeś?
var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'
jest dla mnie w porządku. Nie znaleziono zdarzenia tylko dla powłok interaktywnych. - @St é phaneChazelas: Ach, tak, próbowałem z powłokami interaktywnymi.
:b
modyfikator jest trochę dziwny. - @FranklinYu, na OS / X
sh
to zbudowany z--enable-xpg-echo-default
i--enable-strict-posix-default
w celu zapewnienia zgodności z Uniksem (co obejmujeecho '\t'
wypisywanie karty).
Odpowiedź
Jedyny pozostały powód do napisania skrypt powłoki, zamiast skryptu w dobrym języku skryptowym, oznacza, że ekstremalna przenośność jest nadrzędnym problemem. Starsza wersja /bin/sh
to jedyna rzecz, której możesz być pewien, ale na przykład Perl jest bardziej dostępny na wielu platformach niż Bash. Dlatego nigdy nie pisz skryptów powłoki, które używają funkcji, które nie są prawdziwie uniwersalne – i pamiętaj, że kilku firmowych dostawców Uniksa zamroziło swoje środowisko powłoki przed POSIX.1-2001 .
Istnieje przenośny sposób wykonania tego testu, ale musisz użyć tr
:
[ "x`printf "%s" "$var" | tr -d "$IFS"`" = x ]
(Domyślną wartością $IFS
jest spacja, tabulator i nowa linia.)
(printf
jest samo w sobie przenośny, ale poleganie na nim jest znacznie mniej kłopotliwe niż ustalenie, który wariant echo
posiadasz.)
Komentarze
- To ' jest nieco zagmatwane.Zwykły przenośny sposób sprawdzania, czy ciąg zawiera określone znaki, to z
case
. - @Gilles Nie ' nie sądzę, że ' można napisać
case
glob do wykrywa ciąg, który jest pusty lub zawiera tylko białe znaki. (Byłoby łatwo z wyrażeniem regularnym, alecase
nie ' nie robi wyrażeń regularnych. Konstrukcja w Twojej odpowiedzi wygrała ' nie działa, jeśli zależy ci na nowych wierszach.) - Podałem spacje jako przykład w mojej odpowiedzi, ponieważ ' oto jest pytanie spytany o. ' równie łatwo jest sprawdzić, czy nie ma białych znaków:
case $param in *[![:space:]]*) …
. Jeśli chcesz przetestowaćIFS
znaków, możesz użyć wzorca*[$IFS]*
. - @mikeserv W naprawdę poważnie skryptem obronnym, na początku jawnie ustawiłeś IFS na
<space><tab><newline>
i nigdy więcej go nie dotykasz. Myślałem, że ' może rozpraszać uwagę. - Jeśli chodzi o zmienne we wzorcach, myślę, że działa to we wszystkich wersjach Bourne i wszystkich powłokach POSIX; wymagałoby to dodatkowego kodu do wykrywania wzorców wielkości liter i wyłączania rozwijania zmiennych, a nie mogę ' wymyślić powodu, aby to zrobić. Mam kilka jego instancji w moim
.profile
, który był wykonywany przez wiele powłok Bournea. Oczywiście[$IFS]
wygrał ' Nie zrobię tego, co było zamierzone, jeśliIFS
ma pewne wartości inne niż domyślne wartości (puste (lub nieustawione), zawierające]
, zaczynające się od!
lub^
) .
Odpowiedź
if [[ -n "${variable_name/[ ]*\n/}" ]] then #execute if the the variable is not empty and contains non space characters else #execute if the variable is empty or contains only spaces fi
Komentarze
- to usuwa wszelkie białe znaki, a nie tylko pojedynczą spację, prawda? dzięki
Odpowiedź
Aby sprawdzić, czy zmienna jest pusta lub zawiera spacje, możesz również użyć tego kodu:
${name:?variable is empty}
Komentarze
- Myślę, że Twoja odpowiedź została odrzucona, ponieważ ” lub zawierają spacje ” nie jest prawdą.
- uważaj – to zabija bieżącą powłokę. Lepiej umieścić to w (: $ {podpowłoka?}). Również – to napisze na stderr – prawdopodobnie chcesz przekierować. I najważniejsze , które zwraca wartość zmiennej ' do rzeczywistej wartości, jeśli nie jest nieustawiona lub zerowa. Jeśli jest tam ' polecenie, po prostu je uruchomiłeś. Najlepiej jest ' uruchomić ten test na
:
. - jak zabije powłokę. i możesz to również przetestować, najpierw zdefiniuj
name=aaaa
, a następnie uruchom to polecenieecho ${name:?variable is empty}
wypisze wartość nazwy zmiennej i teraz uruchomi to polecenieecho ${name1:?variable is empty}
wypisze -sh: name1: zmienna jest pusta - Tak –
echo ${name:?variable is empty}
zwróci wartość$name
' jako wartość różną od null lub zabije powłokę. Dlatego z tego samego powodu nie ' nie należyprompt > $randomvar
ani${var?}
– jeśli tam ' jest tam polecenie, ' prawdopodobnie będzie działać – a Ty nie ' nie wiem, co to jest. Powłoka interaktywna nie ' nie musi się kończyć – dlatego Twoja nie ' t. Mimo to, jeśli chcesz zobaczyć kilka testów, jest ich dużo tutaj . Ten nie jest ' tak długi …
Odpowiedź
Kod, który opublikowałeś [[ ! -z $param ]] && echo "I am not zero"
, spowoduje wydrukowanie I am not zero
, jeśli parametr jest nieustawiony / niezdefiniowany lub pusty (w bash, ksh i zsh).
To także wypisz jeśli parametr zawiera tylko spacje (usuń spacje), POSIXly (dla szerszego zakresu powłok):
[ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"
Wyjaśnienie:
-
${param# … }
usuwa początkowy tekst . - Ten początkowy tekst to:
${param%%[! ]*}
- , który rozwija się do wszystkich spacji przed dowolny inny niż spacja znak, tj. Wszystkie początkowe spacje.
Efektem końcowym całego rozwinięcia jest usunięcie wszystkich wiodących spacji.
Ten rozszerzony wynik jest sprawdzany, jeśli ma długość 0.
- Jeśli wynik jest pusty, to albo zmienna była pusta, albo
- usuwając początkowe spacje opróżnił go.
Dlatego jeśli test jest prawdziwy, zmienna była już pusta lub zawierała tylko spacje.
Koncepcja jest łatwa do rozszerzenia na więcej typy znaków. Aby uwzględnić również tabulatory, umieść wyraźną tabulator wewnątrz wyrażenia w nawiasach:
[ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"
lub użyj zmiennej ze znakami, które chcesz usunąć:
var=$" \t" # in ksh, bash, zsh [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"
lub możesz użyć jakiegoś POSIX „wyrażenia klasy znaków” (puste oznacza spację i tabulator):
[ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"
Odpowiedź
Aby sprawdzić, czy zmienna ma tylko spacje, w tym w zmiennej wieloliniowej , spróbuj tego:
[[ $var = *[$" \t\n"]* ]]
Lub z xargs:
[[ -z $(echo $var | xargs) ]]
Lub sedem:
[[ -z $(sed "/^$/d" <<< $var) ]]
Odpowiedź
Spróbuj tego:
$ [[ -z \`echo $n\` ]] && echo zero zero
sed
powiedzieli … tylkoecho
zmienna, którą powiedzieli …${var/pattern/string}
, to nie powinno być ' t, powinno to być[[ -z ${param/ /} ]]
ze spacją między ukośnikami być wzorcem, a nic po nim ciągiem?[[ -z "${param// }" ]]
z pewnością wygląda jakpattern
jest pusty, areplacement string
to pojedyncza spacja. AH! Teraz to widzęif pattern begins with a slash
Brakowało mi tej części. więc wzorzec to/
, a ciąg jest pozostawiony i dlatego pusty. Dzięki.