Назначение команды переменной без псевдонима

Назначение команды переменной без псевдонима

Я только что случайно узнал, что в bash можно присвоить команду переменной без использования alias.

g=date
$g
Mon Jun 27 13:00:40 MYT 2016

Это работает. Вот еще пример:

jj="ping yahoo.com"
$jj
PING yahoo.com (98.138.253.109) 56(84) bytes of data.
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=1 ttl=41 time=347 ms
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=2 ttl=41 time=345 ms
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=3 ttl=41 time=345 ms

Я использую эту версию bashbash --version GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

Я посмотрелстекобмениtldp абс, но не нашел, что мы можем сделать это так. Так это новые возможности bash или что-то, что упускается из виду? Это считаетсязамена команды?

решение1

При интерактивном использовании оболочка считывает строки ввода с терминального устройства. После ввода строки онапроанализированоразделившись нажетоны(слова и операторы). Затем токены или слова расширяются или разрешаются в определенном порядке.

Примечание: в целом, лучше ссылаться на канонический источник информации, такой как проектная документация или отраслевая спецификация, а не на источники из вторых рук, такие как Advanced Bash-Scripting Guide, онлайн-уроки, книги – или даже Stack Exchange :). Такие источники из вторых рук полезны для введения и объяснения концепций на более простом языке, но они обычно не предназначены для полноты или замены официальной документации. Информация в источниках из вторых рук также может быть устаревшей.

В этом случаеСпецификация POSIX для анализа простых командговорится, что

  1. Слова, которые не являются переменными назначениями или перенаправлениями, должны быть расширены. Если после их расширения остаются какие-либо поля, первое поле должно считаться именем команды, а остальные поля — аргументами для команды.

TheРаздел руководства Bash о простом расширении командтакже говорится, что

  1. Слова, которые не являются присвоениями переменных или перенаправлениями, расширяются (см. Shell Expansions). Если после расширения остаются какие-либо слова, первое слово принимается за имя команды, а остальные слова — за аргументы.

решение2

Это не замена команды, этопеременнаяподстановка. Вы не присваиваете команду переменной, вы присваиваете строку. Команда выполняется, когда вы используете переменную, а не во время присваивания.

g=dateсохраняет строку dateв переменной g. Если вы затем запустите echo "$g", это выведет значение g, т.е. date(с последующей новой строкой), поскольку значение gпередается команде echoкак первый аргумент. Если вы запустите "$g", это поместит строку dateв первую позицию команды, то есть это имя команды.

С $jj, в игру вступает второй фактор. Поскольку расширение переменной находится вне кавычек,«оператор split+glob»применяется к значению. В данном случае это означает, что значение jjразбивается на два слова, разделенных пробелом. Таким образом, слово pingоказывается в командной позиции, а слово yahoo.comявляется первым аргументом.

решение3

Это ожидаемое поведение, и оно работает уже много лет. Это полезно для построения команд в скриптах.

Например, иногда мне следует применить декомпрессию к некоторым входным данным перед отправкой их в конвейер (и сжатие к выходным данным после этого), а иногда — нет. Использование bash:

if (( use_compression == 1 )); then
   infilter='gzip -d -c'
   outfilter='gzip -c'
else
   infilter='cat'
   outfilter='cat'
fi

$infilter "$indatafile" | somepipeline | $outfilter >"$outdatafile"

Это подстановка команд? Нет. «Подстановка команд» относится конкретно к замене $(...)варианта с обратными кавычками содержимым его вывода.

Это вместо этогорасширение параметра, т.е. просто заменяет параметры их значениями. Это происходит до того, как команда фактически выполняется, поэтому это и работает.

Это означает, что такие команды, как следующие, также работают в командной строке:

$ decompress='gzip -d -c'
$ ${decompress/g/gun/} filename >unzippedfilename

(который будет выполняться gunzipвместо gzip)

РЕДАКТИРОВАТЬ:О псевдонимах.

В bashруководстве говорится:

Почти для всех целей псевдонимы заменяются функциями оболочки.

... и я согласен.

Псевдонимы хороши для коротких вещей, таких как

alias ls="ls -F"

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

Вероятно, вы не хотите использовать расширения параметров для "псевдонимов" команд в командной строке. Если только это не больно печатать. Расширение параметров также не позволяет выполнять немного более сложные задачи, такие как конвейеризация.

Если вам регулярно приходится выполнять операции средней сложности, используйте для них функции оболочки.

Взяв пример из принятого ответа навопрос U&L(ссылку на которую вы дадите в комментариях ниже):

alias my_File='ls -f | grep -v /'

Этот псевдоним, очевидно, работает, но использование

my_File='ls -f | grep -v /'

не сработает, если вы затем попытаетесь использовать его $my_Fileв качестве команды в командной строке (как объяснено в теме U&L).

С помощью функции оболочки вы также сможете выполнять такие действия, как передача аргументов:

function my_File {
    ls -l "$@" | fgrep -v '/'
}

$ my_File -iF symlink
84416642 lrwxr-xr-x  1 kk  staff  4 Jun 27 09:03 symlink@ -> file

решение4

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

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

Связанный контент