Jak to się ma do zaakceptowanej odpowiedzi podanej w Nieoczekiwanym błędzie operatora ? Mam ten sam błąd podczas używania [ "$1" == "on" ]. Zmiana na [„$ 1” = „on”] rozwiązała problem.
Piotr Dobrogost
78
Miejsca są potrzebne.
TAAPSogeking
6
@JohnFeminella Pisząc w skrypcie bash, powinien mieć jeden, =a nie dwa.
user13107
72
warto zauważyć, że nie możesz używać [ $x -eq "valid" ]. -eqjest operatorem porównania liczb całkowitych, a nie ciągów.
craq
2
@Alex, W jakich przypadkach (jeśli w ogóle) muszę użyć wzorca ["x$yes" == "xyes"], który poprzedza zarówno zmienną, jak i literał ciągiem znakiem x? Czy to relikt dawnych czasów, czy jest naprawdę potrzebny w niektórych sytuacjach?
Dzięki za porównanie kolejności alfabetycznej ciągów
shadi
Mój problem polegał na tym, że $afaktycznie " "otaczał go jako część wartości literału łańcucha, dlatego musiałem użyć znaku zmiany znaczenia, $baby porównać wartości. Znalazłem to po uruchomieniu bash -x ./script.sh, flaga -x pozwala zobaczyć wartość każdego wykonania i pomaga w debugowaniu.
ShahNewazKhan
Zauważ, że porównanie kolejności alfabetycznej nie jest zgodne ze standardem POSIX, więc nie gwarantuje się, że będzie działać na platformach innych niż GNU / powłokach innych niż bash. Gwarantuje się, że tylko operacje na pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html są przenośne.
Charles Duffy
62
Aby porównać ciągi znaków z symbolami wieloznacznymi, użyj
if[["$stringA"==*$stringB*]];then# Do something hereelse# Do Something herefi
Ważne jest, aby symboli wieloznacznych można używać tylko po prawej stronie! Zwróć też uwagę na brakujące "symbole wieloznaczne. (btw: +1 za symbole wieloznaczne!)
Scz
6
Rozszerzenie $stringBmusi być notowane (i, nawiasem mówiąc, lewa strona nie musi być cytowany) if [[ $stringA = *"$stringB"* ]]; then.
gniourf_gniourf
Próbuję użyć tej samej logiki wieloznacznej dla nazwy pliku w ścieżce pliku. Ale to nie działa dla mnie. wypróbowałem wszystkie podane tutaj ciągi znaków zastępczych. ale zawsze tak jest. stringA w moim przypadku jest ścieżką do pliku / tmp / file, a stringB to „file”.
deszcz
35
Nie mogę zgodzić się z jednym z komentarzy w jednym punkcie:
["$x"=="valid"]&& echo "valid"|| echo "invalid"
Nie, to nie jest szalony oneliner
Wygląda to tak, jakby ktoś, niewtajemniczony ...
W pewnym sensie używa wspólnych wzorców jako języka;
A kiedy nauczysz się języka.
Właściwie miło to czytać
Jest to proste wyrażenie logiczne, z jedną specjalną częścią: leniwą oceną operatorów logicznych.
["$x"=="valid"]&& echo "valid"|| echo "invalid"
Każda część jest logicznym wyrażeniem; pierwsze mogą być prawdziwe lub fałszywe, pozostałe dwa są zawsze prawdziwe.
(["$x"=="valid"]&&
echo "valid")||
echo "invalid"
Teraz, gdy jest oceniany, sprawdzany jest pierwszy. Jeśli jest to fałsz, to drugi argument logiki i&& po nim nie ma znaczenia. Pierwsze nie jest prawdą, więc i tak nie może być pierwsze, a drugie być prawdą.
W tym przypadku jest to pierwsza strona logiki lub|| fałsz, ale może być prawdą, jeśli druga strona - trzecia część - jest prawdziwa.
Tak więc trzecia część zostanie poddana ocenie - głównie napisanie wiadomości jako efekt uboczny. (Ma wynik 0dla prawdy, którego nie używamy tutaj)
Pozostałe przypadki są podobne, ale prostsze - i - obiecuję! są - mogą być - łatwe do odczytania!
(Nie mam, ale myślę, że bycie weteranem UNIX z siwą brodą bardzo pomaga w tym.)
... && ... || ...Zwykle boczyć na (przepraszam greybeard Unix weteranem, masz racji przez cały ten czas), a to nie jest semantycznie równoważne if ... then ... else .... Nie martw się, to częsta pułapka .
gniourf_gniourf
6
@gniourf_gniourf OP nie jest zły - nie są też prawdopodobnie ignorantami, jak sugerujesz. ... && ... || ...jest idealnie poprawnym wzorcem i wspólnym idiomem bash. Użycie tego wymaga wcześniejszej wiedzy (co warto pamiętać, jeśli na widowni są początkujący), ale OP ma włosy, aby udowodnić, że wiedzą, jak unikać otwartych pokryw włazów.
ebpa
3
@ebpa Co się stanie, jeśli instrukcja następująca po && zwróci wartość false, wykonanie zostanie wykonane po instrukcji następującej || ? Jeśli tak, to źle i być może właśnie to sugeruje gniourf
TSG
4
Myślałem, że echo to tylko przykład. Instrukcja po && może nadal zwracać niezerową wartość
TSG
2
@gniourf_gniourf +1 za opublikowanie linku do Bash Pitfalls! Bardzo przydatne!
@ytpillai, jest to równoważność. Pamiętaj, że możesz mieć wzory oddzielone |przed, przed ). inStwierdzenie jest równoznaczne thenw ifsprawozdaniu. Można argumentować, że działa na liście wzorców, gdzie każda lista ma własną deklarację co zrobić, jeśli pochodzisz z Pythona. Nie tak substring in string, ale raczej for item in list. *Jeśli chcesz elsespełnić warunek, użyj a jako ostatniego stwierdzenia . Powraca przy pierwszym spotkaniu.
mazunki
18
Poniższy skrypt czyta wiersz po wierszu z pliku o nazwie „testonthis”, a następnie porównuje każdy wiersz z prostym ciągiem, ciągiem znaków specjalnych i wyrażeniem regularnym. Jeśli się nie zgadza, skrypt wypisze wiersz, w przeciwnym razie nie.
Przestrzeń w Bash jest bardzo ważna. Więc będą działać:
["$LINE"!="table_name"]
Ale następujące nie będą:
["$LINE"!="table_name"]
Więc proszę używać jak jest:
cat testonthis |while read LINE
doif["$LINE"!="table_name"]&&["$LINE"!="--------------------------------"]&&[["$LINE"=~[^[:space:]]]]&&[["$LINE"!= SQL*]];then
echo $LINE
fidone
Użyj tego podejścia, aby przejść przez plik. To znaczy, usuń UUoC między innymi.
fedorqui „SO przestań krzywdzić”
To nie jest ważne z tego powodu, bashale ponieważ [jest tak naprawdę zewnętrznym plikiem binarnym (ponieważ which [daje coś podobnego /usr/bin/[)
Patrick Bergner,
11
Prawdopodobnie użyłbym dopasowań wyrażenia regularnego, jeśli dane wejściowe zawierają tylko kilka poprawnych wpisów. Np. Tylko „start” i „stop” są prawidłowymi działaniami.
dla mnie (Mac GNU bash wersja 4.4.12 (1) -release x86_64-apple-darwin17.0.0), muszę użyć if [ "$a"="$b" ]lub to nie działa ... nie mogę mieć spacji wokół równych
Odpowiedzi:
Używanie zmiennych w instrukcjach if
Jeśli chcesz coś zrobić, gdy nie są one zgodne, wymienić
=
z!=
. Możesz przeczytać więcej o operacjach na łańcuchach i operacjach arytmetycznych w odpowiedniej dokumentacji.Dlaczego używamy cytatów
$x
?Chcesz znaleźć cudzysłowy
$x
, ponieważ jeśli jest pusty, skrypt Bash napotka błąd składniowy, jak pokazano poniżej:Niestandardowe użycie
==
operatoraZauważ, że Bash pozwala
==
na równe traktowanie[
, ale nie jest to standard .Użyj pierwszego przypadku, w którym cudzysłowy
$x
są opcjonalne:lub użyj drugiego przypadku:
źródło
[ "$1" == "on" ]
. Zmiana na [„$ 1” = „on”] rozwiązała problem.=
a nie dwa.[ $x -eq "valid" ]
.-eq
jest operatorem porównania liczb całkowitych, a nie ciągów.["x$yes" == "xyes"]
, który poprzedza zarówno zmienną, jak i literał ciągiem znakiemx
? Czy to relikt dawnych czasów, czy jest naprawdę potrzebny w niektórych sytuacjach?Lub, jeśli nie potrzebujesz innej klauzuli:
źródło
echo
może się nie powieść.[ "$X" == "valid" ] || ( echo invalid && false ) && echo "valid"
.{ echo invalid && false; }
jest bardziej wydajny( echo invalid && false )
, ponieważ unika płacenia za niepotrzebną podpowłokę.Uwagi:
if
a[
i]
są ważne>
i<
są operatorami przekierowania, więc unikaj go za pomocą\>
i\<
odpowiednio dla ciągów.źródło
$a
faktycznie" "
otaczał go jako część wartości literału łańcucha, dlatego musiałem użyć znaku zmiany znaczenia,$b
aby porównać wartości. Znalazłem to po uruchomieniubash -x ./script.sh
, flaga -x pozwala zobaczyć wartość każdego wykonania i pomaga w debugowaniu.Aby porównać ciągi znaków z symbolami wieloznacznymi, użyj
źródło
"
symbole wieloznaczne. (btw: +1 za symbole wieloznaczne!)$stringB
musi być notowane (i, nawiasem mówiąc, lewa strona nie musi być cytowany)if [[ $stringA = *"$stringB"* ]]; then
.Nie mogę zgodzić się z jednym z komentarzy w jednym punkcie:
Nie, to nie jest szalony oneliner
Wygląda to tak, jakby ktoś, niewtajemniczony ...
W pewnym sensie używa wspólnych wzorców jako języka;
A kiedy nauczysz się języka.
Właściwie miło to czytać
Jest to proste wyrażenie logiczne, z jedną specjalną częścią: leniwą oceną operatorów logicznych.
Każda część jest logicznym wyrażeniem; pierwsze mogą być prawdziwe lub fałszywe, pozostałe dwa są zawsze prawdziwe.
Teraz, gdy jest oceniany, sprawdzany jest pierwszy. Jeśli jest to fałsz, to drugi argument logiki i
&&
po nim nie ma znaczenia. Pierwsze nie jest prawdą, więc i tak nie może być pierwsze, a drugie być prawdą.W tym przypadku jest to pierwsza strona logiki lub
||
fałsz, ale może być prawdą, jeśli druga strona - trzecia część - jest prawdziwa.Tak więc trzecia część zostanie poddana ocenie - głównie napisanie wiadomości jako efekt uboczny. (Ma wynik
0
dla prawdy, którego nie używamy tutaj)Pozostałe przypadki są podobne, ale prostsze - i - obiecuję! są - mogą być - łatwe do odczytania!
(Nie mam, ale myślę, że bycie weteranem UNIX z siwą brodą bardzo pomaga w tym.)
źródło
... && ... || ...
Zwykle boczyć na (przepraszam greybeard Unix weteranem, masz racji przez cały ten czas), a to nie jest semantycznie równoważneif ... then ... else ...
. Nie martw się, to częsta pułapka .... && ... || ...
jest idealnie poprawnym wzorcem i wspólnym idiomem bash. Użycie tego wymaga wcześniejszej wiedzy (co warto pamiętać, jeśli na widowni są początkujący), ale OP ma włosy, aby udowodnić, że wiedzą, jak unikać otwartych pokryw włazów.możesz również użyć przypadku użycia / esac
źródło
|
przed, przed)
.in
Stwierdzenie jest równoznacznethen
wif
sprawozdaniu. Można argumentować, że działa na liście wzorców, gdzie każda lista ma własną deklarację co zrobić, jeśli pochodzisz z Pythona. Nie taksubstring in string
, ale raczejfor item in list
.*
Jeśli chceszelse
spełnić warunek, użyj a jako ostatniego stwierdzenia . Powraca przy pierwszym spotkaniu.Poniższy skrypt czyta wiersz po wierszu z pliku o nazwie „testonthis”, a następnie porównuje każdy wiersz z prostym ciągiem, ciągiem znaków specjalnych i wyrażeniem regularnym. Jeśli się nie zgadza, skrypt wypisze wiersz, w przeciwnym razie nie.
Przestrzeń w Bash jest bardzo ważna. Więc będą działać:
Ale następujące nie będą:
Więc proszę używać jak jest:
źródło
bash
ale ponieważ[
jest tak naprawdę zewnętrznym plikiem binarnym (ponieważwhich [
daje coś podobnego/usr/bin/[
)Prawdopodobnie użyłbym dopasowań wyrażenia regularnego, jeśli dane wejściowe zawierają tylko kilka poprawnych wpisów. Np. Tylko „start” i „stop” są prawidłowymi działaniami.
Zauważ, że zmienię małe litery
$ACTION
, używając podwójnego przecinka. Zauważ też, że to nie zadziała w przypadku zbyt starych wersji bash.źródło
Przykłady Bash 4+. Uwaga: niestosowanie cudzysłowów spowoduje problemy, gdy słowa zawierają spacje itp. Zawsze cytuj w Bash, IMO.
Oto kilka przykładów w Bash 4+:
Przykład 1, sprawdź ciąg „tak” (bez rozróżniania wielkości liter):
Przykład 2, sprawdź ciąg „tak” (bez rozróżniania wielkości liter):
Przykład 3, sprawdź ciąg „tak” (rozróżniana jest wielkość liter):
Przykład 4, sprawdź ciąg „tak” (rozróżniana jest wielkość liter):
Przykład 5, dopasowanie ścisłe (wielkość liter ma znaczenie):
Przykład 6, dopasowanie ścisłe (bez rozróżniania wielkości liter):
Przykład 7, dopasowanie ścisłe:
Cieszyć się.
źródło
if [ "$a"="$b" ]
lub to nie działa ... nie mogę mieć spacji wokół równychZrobiłem to w sposób zgodny z Bash i Dash (sh):
źródło
(
a nieużywaniem go?