Jaka jest różnica między plikiem grep apple a plikiem grep „apple”?

22

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ę).

John Stacen
źródło

Odpowiedzi:

45

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.

David Foerster
źródło
2
Jest to również widoczne w przypadku symboli wieloznacznych. Jeśli to zrobisz 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 polecenie find . -name *.txtspowoduje nieoczekiwane zachowanie, jeśli w bieżącym katalogu znajduje się plik txt. W takim przypadku lepiej użyć cudzysłowów.
SztupY
4
Kolejną ważną kwestią jest różnica między podwójnymi cudzysłowami ( ") 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.).
Paddy Landau
23

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.

AsymLabs
źródło
Jak użyłbyś podwójnych cudzysłowów w podwójnych cudzysłowach? Czy to literówka? I dlaczego zamiast tego mam unikać podwójnych cudzysłowów w pojedynczych cudzysłowach? Chyba pomieszałeś zdania?
Bajt Dowódca
@ByteCommander Tak, koncepcja podwójnych cudzysłowów umieszczonych w podwójnych cudzysłowach jest używana dość często - zobacz ten post jako wybitny działający przykład. Zwykle robi się to w celu ochrony ciągów zawierających spacje, często w odniesieniu do ciągów ścieżek. Podwójnych cudzysłowów można używać w pojedynczych cudzysłowach ze znakami ucieczki lub bez nich, ale będą one interpretowane dosłownie, to znaczy nie będą prowadzić do oceny. Wyjaśnię ten punkt w poście.
AsymLabs,