
Я попробовал следующие команды
variable='one|name'
echo $variable
Выходной сигнал:
one|name
тогда как echo one|name
выдает ошибку No command 'name' found
. Это разумно, поскольку bash обрабатывает |
как канал и пытается выполнить команду name
с one
входными данными.
Но почему echo $variable
print one|name
? После раскрытия параметров и переменных не должно ли это быть эквивалентно echo one|name
?
Версия:
GNU bash, version 4.3.11(1)-release (i686-pc-linux-gnu)
решение1
Нет, не должно, из-за способаbash
выполнить команду.
При вводе команды выполняется ее echo one|name
синтаксический bash
анализ, обрабатывается |
как токен конвейера, поэтому |
выполняется конвейер.
Когда вы вводите echo $variable
, поскольку разбор токена происходит до расширения переменной, bash
команда разделяется на две части, echo
и $variable
. После этого выполняется расширение переменной, расширение $variable
до one|name
. В этом случае one|name
— это строка, |
является частью строки и не может рассматриваться как токен конвейера (конечно,фраза распознавания токенабыло сделано). Единственное, что может быть особенным, если IFS
переменная содержит |
, bash
будет использоваться |
в качестве разделителя для выполнения разделения полей:
$ variable='one|name'
$ IFS='|'
$ echo $variable
one name
решение2
Причина в способе Bash
расширения переменной.
Вместо того, чтобы расширять переменную до , one|name
он расширяет переменную до "one|name"
. Так что здесь, поскольку значение заключено в кавычки, оно рассматривается как строка, а не как команда.
Ниже приведен strace
вывод команды, показывающий, как она расширяется.
$ variable='one|name'
$ strace echo $variable
execve("/bin/echo", ["echo", "one|name"], [/* 33 vars */]) = 0
brk(0) = 0x9cc7000
решение3
Кавычки являются частью созданной вами строки.
Если бы ты это сделал
variable=one|name
echo $variable
результат будет таким, как и ожидалось. Но это можно сделать только в скрипте (спасибо за полезный комментарий).