Poniższa składnia bash sprawdza, czy param
nie jest pusta:
[[ ! -z $param ]]
Na przykład:
param=""
[[ ! -z $param ]] && echo "I am not zero"
Brak wyników i jest w porządku.
Ale gdy param
jest pusty, z wyjątkiem jednego (lub więcej) znaków spacji, sprawa jest inna:
param=" " # one space
[[ ! -z $param ]] && echo "I am not zero"
Wyjście „Nie jestem zero”.
Jak mogę zmienić test, aby uznać zmienne zawierające tylko znaki spacji za puste?
bash
shell
shell-script
string
maihabunash
źródło
źródło
man test
:-z STRING - the length of STRING is zero
. Jeśli chcesz usunąć wszystkie spacje$param
, użyj${param// /}
trim()
w żadnym * nixie nie ma żadnej prostej funkcji? Tyle różnych hacków, by osiągnąć coś tak prostego ...[[ ! -z $param ]]
jest to równoważnetest ! -z $param
.Odpowiedzi:
Po pierwsze, zauważ, że
-z
test jest wyraźnie dla:Oznacza to, że łańcuch zawierający tylko spacje nie powinien być prawdziwy pod
-z
, ponieważ ma niezerową długość.To, czego chcesz, to usunąć spacje ze zmiennej za pomocą rozszerzenia parametru zastępującego wzorzec :
To rozszerza
param
zmienną i zastępuje wszystkie dopasowania wzorca(pojedynczą spacją) niczym, więc ciąg zawierający tylko spacje zostanie rozwinięty do pustego ciągu.
Sedna jak to działa jest to, że
${var/pattern/string}
zastępuje pierwszy najdłuższy meczpattern
zstring
. Kiedypattern
zaczyna się od/
(jak wyżej), zastępuje wszystkie dopasowania. Ponieważ zamiana jest pusta, możemy pominąć końcową/
istring
wartość:Po tym wszystkim kończymy
${param// }
na usuwaniu wszystkich spacji.Zauważ, że chociaż jest obecny w
ksh
(skąd pochodzi),zsh
ibash
, że składnia ta nie jest POSIX i nie powinna być używana wsh
skryptach.źródło
sed
powiedzieli ... tylkoecho
zmienną, którą powiedzieli ...${var/pattern/string}
czy nie powinno być[[ -z ${param/ /} ]]
z odstępem między ukośnikami, który ma być wzorem, a niczym po łańcuchu?[[ -z "${param// }" ]]
pewno wygląda napattern
pustą ireplacement string
pojedynczą spację. AH! Widzę to terazif pattern begins with a slash
, tęskniłem za tą częścią. więc wzór jest,/
a łańcuch zostaje pominięty i dlatego jest pusty. Dzięki.Najłatwiejszym sposobem sprawdzenia, czy łańcuch zawiera tylko znaki w autoryzowanym zestawie, jest sprawdzenie obecności nieautoryzowanych znaków. Dlatego zamiast sprawdzać, czy łańcuch zawiera tylko spacje, sprawdź, czy łańcuch zawiera znak inny niż spacja. W bash, ksh lub zsh:
„Składa się tylko ze spacji” obejmuje przypadek pustej (lub nieustawionej) zmiennej.
Możesz przetestować dowolny znak spacji. Użyj,
[[ $param = *[^[:space:]]* ]]
aby użyć ustawień regionalnych lub jakiejkolwiek wyraźnej listy białych znaków, które chcesz przetestować, np.[[ $param = *[$' \t\n']* ]]
Aby sprawdzić spację, tabulator lub znak nowej linii.Dopasowywanie łańcucha do wzorca z
=
wnętrzem[[ … ]]
jest rozszerzeniem ksh (występującym również w bash i zsh). W dowolnym stylu Bourne / POSIX możesz użyćcase
konstrukcji, aby dopasować ciąg do wzorca. Zauważ, że standardowe wzorce powłoki służą!
do negowania zestawu znaków, a nie^
jak w większości składni wyrażeń regularnych.Aby przetestować znaki spacji,
$'…'
składnia jest specyficzna dla ksh / bash / zsh; możesz dosłownie wstawić te znaki w skrypcie (pamiętaj, że nowa linia musi znajdować się w cudzysłowach, ponieważ ukośnik + nowa linia rozwija się do zera), lub wygeneruj je, np.źródło
${var?not set}
- przekazanie tego testu i przetrwanie zapewni, że zmienna dopasowana przez ciebie*)
case
spowoduje ostateczne działanie na przykład odpowiedz.[[ $param = *[!\ ]* ]]
wmksh
.POSIXly:
Aby rozróżnić puste , niepuste , puste , rozbrojone :
[:blank:]
jest dla znaków odstępów w poziomie (spacja i tabulacja w ASCII, ale prawdopodobnie jest kilka innych w twoim języku; niektóre systemy będą zawierały spacje nierozdzielające (jeśli są dostępne), niektóre nie). Jeśli chcesz, jak również (jak znak nowej linii lub form-feed) pionowe znaki odstępów, wymienić[:blank:]
z[:space:]
.źródło
zsh
wygląda na to, że ma z tym problem[![:blank:]]
, to przebicie:b
jest nieprawidłowym modyfikatorem. Wsh
iksh
naśladować, wzbudza to wydarzenie, którego nie znaleziono dla[
var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'
jest dla mnie OK. Nie znaleziono zdarzenia dotyczącego tylko interaktywnych powłok.:b
Nieważny modyfikator jest nieco dziwne.sh
jestbash
zbudowany--enable-xpg-echo-default
i--enable-strict-posix-default
tak być zgodny z systemem UNIX (która polega naecho '\t'
wysyłaniu kartę).Jedynym pozostałym powodem do napisania skryptu powłoki, zamiast skryptu w dobrym języku skryptowym, jest to, że ekstremalna przenośność jest nadrzędnym problemem. Dziedzictwo
/bin/sh
jest jedyną rzeczą, którą możesz mieć pewność, że masz, ale na przykład Perl jest bardziej dostępny na wiele platform niż Bash. Dlatego nigdy nie pisz skryptów powłoki, które używają funkcji, które nie są naprawdę uniwersalne - i pamiętaj, że kilku zastrzeżonych dostawców uniksowych zamroziło swoje środowisko powłoki przed POSIX.1-2001 .Istnieje przenośny sposób na wykonanie tego testu, ale musisz użyć
tr
:(
$IFS
Dogodnie domyślną wartością jest spacja, tabulator i nowa linia).(
printf
Wbudowany sam w sobie jest niesamowicie przenośny, ale poleganie na nim jest znacznie mniej kłopotliwe niż ustalenie, który wariantecho
masz.)źródło
case
.case
glob, aby wykryć ciąg, który jest albo pusty, albo zawiera tylko białe znaki. (Byłoby to łatwe z wyrażeniemcase
regularnym , ale nie robi wyrażeń regularnych. Konstrukt w odpowiedzi nie zadziała, jeśli zależy Ci na nowych wierszach.)case $param in *[![:space:]]*) …
. Jeśli chcesz przetestowaćIFS
znaki, możesz użyć wzorca*[$IFS]*
.<space><tab><newline>
na początku, a następnie nigdy go nie dotykasz. Myślałem, że to rozproszy..profile
które zostały wykonane przez wiele pocisków Bourne'a. Oczywiście[$IFS]
nie zrobi tego, co było zamierzone, jeśliIFS
ma pewne wartości inne niż domyślne (puste (lub nieuzbrojone), zawierające]
, zaczynające się od!
lub^
).źródło
Do testowania, czy zmienna jest pusta lub zawiera spacje, możesz również użyć tego kodu:
źródło
:
.name=aaaa
a następnie uruchom to polecenieecho ${name:?variable is empty}
, wypisze wartość zmiennej nazwa, a teraz uruchom to polecenieecho ${name1:?variable is empty}
, wypisze -sh: nazwa1: zmienna jest pustaecho ${name:?variable is empty}
albo oceni$name
wartość inną niż null, albo zabije powłokę. Z tego samego powoduprompt > $randomvar
nie powinieneś tego robić${var?}
- jeśli jest tam polecenie, prawdopodobnie zadziała - i nie wiesz, co to jest. Interaktywna powłoka nie musi wychodzić - dlatego twoja nie. Jeśli jednak chcesz zobaczyć jakieś testy, jest ich tutaj wiele . . Ten nie jest tak długi ...Aby sprawdzić, czy zmienna nie jest ustawiona, pusta (ma wartość zerową) lub zawiera tylko spacje:
Wyjaśnienie:
${param%%[! ]*}
usuwa od pierwszej spacji do końca.-z
, echoempty
.Powyższe jest kompatybilne z POSIX i działa na każdym potomku Bourne'a.
Jeśli chcesz rozszerzyć to na karty, dołącz wyraźną kartę:
lub użyj zmiennej ze znakami, które chcesz usunąć:
lub możesz użyć „wyrażenia klasy znaków” POSIX (puste oznacza spację i tabulator):
Ale to zawiedzie w mksh, lksh i posh.
źródło
Spróbuj tego:
źródło