Jaka jest różnica między grep apple filei 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 filei 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ż applenie zawiera takich znaków.
Ale rozważ inny przykład: grep apple tree filewyszuka słowo applew plikach treei file, podczas gdy grep "apple tree" fileprzeszuka słowo apple treew 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 filedał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 USERzawiera 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 *.txtspowoduje nieoczekiwane zachowanie, jeśli w bieżącym katalogu znajduje się plik txt. W takim przypadku lepiej użyć cudzysłowów.