Команда echo
не включает полный текст, который я даю. Например, если я делаю:
$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '
Это выводит:
echo PARAM=` grep $ARG /var/tmp/setfile | awk {print } `
Одиночные кавычки ( '
), которые были в моей команде echo, не включены. Если я переключусь на двойные кавычки:
$ echo " echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` "
echo
вообще ничего не выводит! Почему он пропускает одинарные кавычки в первом примере и ничего не выводит во втором? Как мне заставить его выводить именно то, что я набрал?
Ответы:
Ваша оболочка интерпретирует кавычки,
'
и"
прежде, чем они до них дойдутecho
. Я обычно просто помещаю двойные кавычки вокруг моего аргумента, чтобы повторить, даже если они не нужны; например:Итак, в первом примере, если вы хотите включить в вывод вывод буквенных кавычек, их нужно либо экранировать:
Или они уже должны использоваться внутри аргумента в кавычках (но это не может быть тот же тип цитаты, или вам все равно придется избегать его):
Во втором примере вы выполняете подстановку команд в середине строки:
Вещи, которые начинаются с
$
, также обрабатываются специально оболочкой - она обрабатывает их как переменные и заменяет их значениями. Поскольку, скорее всего, ни одна из этих переменных не установлена в вашей оболочке, она просто запускаетсяПоскольку он
grep
видит только один аргумент, он предполагает, что аргумент - это шаблон, который вы ищете, и что место, из которого он должен читать данные, - это stdin, поэтому он блокирует ожидание ввода. Вот почему ваша вторая команда, кажется, просто зависает.Этого не произойдет, если вы заключите аргумент в одинарные кавычки (именно поэтому ваш первый пример почти сработал), так что это один из способов получить желаемый результат:
Вы также можете заключить его в двойные кавычки, но тогда вам нужно будет экранировать
$
s, чтобы оболочка не преобразовывала их как переменные, и обратные галочки, чтобы оболочка не запускала подстановку команд сразу:источник
Я не буду вдаваться в подробности того, почему ваши попытки ведут себя так, как они делают, потому что ответ Майкла Мрозека хорошо освещает это. В двух словах, все между одинарными кавычками (
'…'
) интерпретируется буквально (и, в частности, первый'
отмечает конец буквальной строки), тогда как`
и$
сохраняют свое особое значение между"…"
.В одинарных кавычках нет кавычек, поэтому нельзя помещать одинарные кавычки в одинарные кавычки. Однако есть идиома, которая выглядит так:
Это печатает
foo'bar
, потому что аргумент toecho
состоит из трехсимвольной строки в одинарных кавычкахfoo
, объединенной с одним символом'
(полученным путем защиты символа'
от его особого значения в предыдущем\
), объединенной со строкой из трех символов в одинарных кавычкахbar
. Так что, хотя это не совсем то, что происходит за кулисами, вы можете представить'\''
себе способ включения одинарных кавычек в строку в одинарных кавычках.Если вы хотите напечатать сложные многострочные строки, лучшим инструментом является документ здесь . Здесь документ состоит из двух символов,
<<
за которыми следует маркер, например<<EOF
несколько строк текста, а затем маркер конца на одной строке. Если маркер заключен в кавычки каким-либо образом ('EOF'
или"EOF"
или\EOF
«E», «OF» или…), то текст интерпретируется буквально (как внутри одинарных кавычек, за исключением того, что даже'
является обычным символом). Если маркер вообще не заключен в кавычки, то текст интерпретируется как строка в двойных кавычках,$\`
сохраняя свой особый статус (но"
и переводы строк интерпретируются буквально).источник
Хорошо, это будет работать:
Тестирование здесь: -
источник
Предложение Жиля об использовании документа здесь действительно хорошо, и даже работает в таких скриптовых языках, как Perl. В качестве конкретного примера, основанного на его ответе на вопрос ОП,
Конечно, этот пример немного надуманный, но я нашел его полезным, скажем, для отправки операторов SQL
psql
(вместоcat
).(Обратите внимание, что любой не алфавитно-цифровой непробельный символ можно использовать вместо
#
приведенной выше общей конструкции цитирования, но хеш, похоже, хорошо выделяется для этого примера и не рассматривается как комментарий.)источник
Давайте возьмем вашу команду
и сначала разбить его на слова, используя пробел без кавычек в качестве разделителя:
Далее мы делаем расширение параметров: расширяем,
$…
но не внутри'…'
. Поскольку$2
он пуст (если вы не установили его, например, черезset -- …
), он будет заменен пустой строкой.Далее сделайте удаление цитаты.
Эти аргументы затем передаются в echo, который выводит их один за другим, разделенные одним пробелом.
Я надеюсь, что эта пошаговая инструкция сделает наблюдаемое поведение более понятным. Чтобы избежать этой проблемы, избегайте одинарных кавычек:
Это завершит строку в одинарных кавычках, затем добавит (экранированную) одинарную кавычку к слову, а затем начнет новую строку в одинарных кавычках, не разбивая слово на части.
источник