В чем разница между grep apple file
и grep "apple" file
? Что делает установка кавычек? Они оба работают и делают одно и то же (отображают одну и ту же строку).
В чем разница между grep apple file
и grep "apple" file
? Что делает установка кавычек? Они оба работают и делают одно и то же (отображают одну и ту же строку).
Ответы:
Кавычки влияют на то, какие символы ваша оболочка считает особенными, и имеют синтаксическое значение. В вашем примере это не имеет значения, потому что не 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 игнорировать особое значение следующего символа и трактовать его буквально.
"
) и одинарными кавычками ( '
). Одинарные кавычки запрещают интерпретацию определенных символов, например $
, тогда как двойные кавычки позволяют интерпретацию. Например, grep '${USER}'
будет искать текст ${USER}
, тогда как grep "${USER}"
будет искать текст, который USER
содержит переменная (например johnstacen
).
Двойные кавычки разрешают оценку, одинарные кавычки запрещают оценку, никакие кавычки не позволяют расширение подстановочных знаков при использовании в командной строке. В качестве надуманных примеров:
[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 расширял что-то в элементы (например, массив), я использую одинарные кавычки для буквенных строк, которые нельзя изменять, и я свободно использую двойные кавычки для переменных которые могут вернуть любой тип строки. Это необходимо для сохранения пробелов и специальных символов.
grep a*b equations.txt
он будет искатьa*b
, если в текущем каталоге нет файла, начинающегося с a и заканчивающегося на b, и в этом случае (поскольку (ba) sh будет расширять имена файлов в командной строке), grep будет вызываться с помощью завершить разные параметры, в результате чего разные результаты. Обычно это больше связано с поиском, так как команда likefind . -name *.txt
приведет к непредвиденному поведению, если в текущем каталоге есть текстовый файл. В этом случае лучше использовать кавычки.