Jaka jest różnica między grep apple file
i grep "apple" file
? Co robi wstawianie cudzysłowów? Wydaje się, że oba działają i robią dokładnie to samo (wyświetlają tę samą linię).
Jaka jest różnica między grep apple file
i grep "apple" file
? Co robi wstawianie cudzysłowów? Wydaje się, że oba działają i robią dokładnie to samo (wyświetlają tę samą linię).
Odpowiedzi:
Cudzysłowy mają wpływ na to, jakie znaki twoja powłoka uważa za specjalne i mają znaczenie składniowe. W twoim przykładzie nie robi to różnicy, ponieważ apple
nie zawiera takich znaków.
Ale rozważ inny przykład: grep apple tree file
wyszuka słowo apple
w plikach tree
i file
, podczas gdy grep "apple tree" file
przeszuka słowo apple tree
w pliku file
. Znaki cudzysłowu informują bash, że słowo spacja "apple tree"
nie rozpoczyna nowego parametru, ale powinno być częścią bieżącego parametru. grep apple\ tree file
dałoby ten sam wynik, ponieważ \
każe bashowi zignorować specjalne znaczenie poniższego znaku i traktować go dosłownie.
"
) i pojedynczymi cudzysłowami ( '
). Pojedyncze cudzysłowy uniemożliwiają interpretację niektórych znaków, np. $
Podwójne cudzysłowy umożliwiają interpretację. Np. Wyszuka grep '${USER}'
tekst ${USER}
, podczas gdy grep "${USER}"
wyszuka tekst, który USER
zawiera zmienna (np johnstacen
.).
Podwójne cudzysłowy pozwalają na ocenę, pojedyncze cudzysłowy uniemożliwiają ocenę, brak cudzysłowu pozwala na interpretację symboli wieloznacznych, gdy są używane w wierszu poleceń. Jako wymyślone przykłady:
[user@work test]$ ls .
A.txt B.txt C.txt D.cpp
# The following is the same as writing echo 'A.txt B.txt C.txt D.cpp'
[user@work test]$ echo *
A.txt B.txt C.txt D.cpp
[user@work test]$ echo "*"
*
[user@work test]$ echo '*'
*
# The following is the same as writing echo 'A.txt B.txt C.txt'
[user@work test]$ echo *.txt
A.txt B.txt C.txt
[user@work test]$ echo "*.txt"
*.txt
[user@work test]$ echo '*.txt'
*.txt
[user@work test]$ myname=is Fred; echo $myname
bash: Fred: command not found
[user@work test]$ myname=is\ Fred; echo $myname
is Fred
[user@work test]$ myname="is Fred"; echo $myname
is Fred
[user@work test]$ myname='is Fred'; echo $myname
is Fred
Zrozumienie sposobu działania cytatów jest kluczowe dla zrozumienia Bash. Na przykład:
# for will operate on each file name separately (like an array), looping 3 times.
[user@work test]$ for f in $(echo *txt); do echo "$f"; done;
A.txt
B.txt
C.txt
# for will see only the string, 'A.txt B.txt C.txt' and loop just once.
[user@work test]$ for f in "$(echo *txt)"; do echo "$f"; done;
A.txt B.txt C.txt
# this just returns the string - it can't be evaluated in single quotes.
[user@work test]$ for f in '$(echo *txt)'; do echo "$f"; done;
$(echo *txt)
Możesz użyć pojedynczych cudzysłowów, aby przekazać polecenie przez zmienną. Pojedyncze cytaty zapobiegną ocenie. Podwójne cytaty zostaną ocenione.
# This returns three distinct elements, like an array.
[user@work test]$ echo='echo *.txt'; echo $($echo)
A.txt B.txt C.txt
# This returns what looks like three elements, but it is actually a single string.
[user@work test]$ echo='echo *.txt'; echo "$($echo)"
A.txt B.txt C.txt
# This cannot be evaluated, so it returns whatever is between quotes, literally.
[user@work test]$ echo='echo *.txt'; echo '$($echo)'
$($echo)
Możesz używać pojedynczych cudzysłowów wewnątrz podwójnych cudzysłowów i możesz używać podwójnych cudzysłowów wewnątrz podwójnych cudzysłowów, ale podwójne cudzysłowy wewnątrz pojedynczych cudzysłowów nie powinny być wykonywane (bez ich ucieczki) nie będą oceniane, będą interpretowane dosłownie. Pojedyncze cytaty w pojedynczych cudzysłowach nie powinny być wykonywane (bez ich ucieczki).
Musisz dokładnie zrozumieć cytaty, aby skutecznie korzystać z Bash. Bardzo ważne!
Zasadniczo nie używam cudzysłowów, jeśli chcę, aby Bash rozwinął coś do elementów (takich jak tablica), używam pojedynczych cudzysłowów dla dosłownych ciągów znaków, których nie należy zmieniać, i swobodnie używam podwójnych cudzysłowów dla zmiennych które prawdopodobnie zwrócą dowolny typ ciągu. Ma to na celu zachowanie spacji i znaków specjalnych.
grep a*b equations.txt
, będzie szukała*b
, chyba że w bieżącym katalogu znajduje się plik zaczynający się od a, kończący się na b, w którym to przypadku (ponieważ (ba) sh rozwinie nazwy plików w wierszu poleceń) grep zostanie wywołany z wypełnić różne parametry, co daje różne wyniki. Zwykle jest to większy problem z find, ponieważ takie poleceniefind . -name *.txt
spowoduje nieoczekiwane zachowanie, jeśli w bieżącym katalogu znajduje się plik txt. W takim przypadku lepiej użyć cudzysłowów.