В чем разница между файлом grep apple и файлом grep «apple»?

22

В чем разница между grep apple fileи grep "apple" file? Что делает установка кавычек? Они оба работают и делают одно и то же (отображают одну и ту же строку).

Джон Стейсен
источник

Ответы:

45

Кавычки влияют на то, какие символы ваша оболочка считает особенными, и имеют синтаксическое значение. В вашем примере это не имеет значения, потому что не appleсодержит таких символов.

Но рассмотрим другой пример: grep apple tree fileбудет искать слово appleв файлах treeи file, тогда как grep "apple tree" fileбудет искать слово apple treeв файле file. Кавычки говорят bash, что слово space in "apple tree"не запускает новый параметр, но должно быть частью текущего параметра. grep apple\ tree fileприведет к тому же результату, потому что \говорит bash игнорировать особое значение следующего символа и трактовать его буквально.

Дэвид Фёрстер
источник
2
Это также видно с подстановочными знаками. Если вы это сделаете, grep a*b equations.txtон будет искать a*b, если в текущем каталоге нет файла, начинающегося с a и заканчивающегося на b, и в этом случае (поскольку (ba) sh будет расширять имена файлов в командной строке), grep будет вызываться с помощью завершить разные параметры, в результате чего разные результаты. Обычно это больше связано с поиском, так как команда like find . -name *.txtприведет к непредвиденному поведению, если в текущем каталоге есть текстовый файл. В этом случае лучше использовать кавычки.
Штупы
4
Другим важным моментом является разница между двойными кавычками ( ") и одинарными кавычками ( '). Одинарные кавычки запрещают интерпретацию определенных символов, например $, тогда как двойные кавычки позволяют интерпретацию. Например, grep '${USER}'будет искать текст ${USER}, тогда как grep "${USER}"будет искать текст, который USERсодержит переменная (например johnstacen).
Пэдди Ландау
23

Двойные кавычки разрешают оценку, одинарные кавычки запрещают оценку, никакие кавычки не позволяют расширение подстановочных знаков при использовании в командной строке. В качестве надуманных примеров:

[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

Понимание того, как работают цитаты, имеет решающее значение для понимания Bash. Например:

# 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)

Вы можете использовать одинарные кавычки для передачи команды через переменную. Одинарные кавычки помешают оценке. Двойные кавычки оценят.

# 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)

Вы можете использовать одинарные кавычки внутри двойных кавычек, и вы можете использовать двойные кавычки внутри двойных кавычек, но двойные кавычки внутри одинарных кавычек не должны выполняться (без экранирования), они не будут оцениваться, они будут интерпретироваться буквально. Одиночные кавычки в одинарных кавычках не должны выполняться (без их выхода).

Чтобы эффективно использовать Bash, вам необходимо получить полное представление о кавычках. Очень важный!

Как правило, я не использую кавычки, если я хочу, чтобы Bash расширял что-то в элементы (например, массив), я использую одинарные кавычки для буквенных строк, которые нельзя изменять, и я свободно использую двойные кавычки для переменных которые могут вернуть любой тип строки. Это необходимо для сохранения пробелов и специальных символов.

AsymLabs
источник
Как бы вы использовали двойные кавычки внутри двойных кавычек ??? Это опечатка? И почему я должен избегать двойных кавычек внутри одинарных кавычек? Я полагаю, вы перепутали предложения?
Byte Commander
@ByteCommander Да, концепция двойных кавычек, помещенных в двойные кавычки, используется довольно часто - см. Этот пост для яркого рабочего примера. Обычно это делается для защиты строк, содержащих пробелы, часто по отношению к строкам пути. Двойные кавычки могут использоваться в одинарных кавычках с экранированием или без него, но они будут интерпретироваться буквально, то есть они не приведут к оценке. Я проясню этот момент в посте.
AsymLabs