Как разделить несколько команд, переданных eval в bash



Я пытаюсь вычислить несколько строк команд оболочки с помощью eval, но когда я пытаюсь разрешить переменные с eval, разделенными новой строкой n, переменные не разрешаются.



x='echo a'
y='echo b'
z="$xn$y"
eval $x
eval $y
eval $z


Который выводит:



a
b
anecho b


Последняя команда дает anecho b, и, по-видимому, n трактовалось там как n. Итак, есть ли способ оценить несколько строк команд (скажем, разделенных n)?

628   4  

4 ответов:

\n это не новая строка; это escape-последовательность, которая в некоторых ситуациях будет переведена в новую строку, но вы не использовали ее ни в одной из этих ситуаций. Переменная $z не содержит новой строки, а только обратную косую черту, за которой следует "n". В результате, это то, что на самом деле выполняется:

$ echo a\necho b
anecho b

Вы можете либо использовать точку с запятой (которая не требует перевода), либо использовать \n в контексте, где она будет переведена в новая строка:

$ newline=$'\n'
$ x='echo a'
$ y='echo b'
$ z="$x$newline$y"
$ eval "$z"
a
b
Обратите внимание на двойные кавычки вокруг "$z" - они действительно критичны здесь. Без них bash будет разбивать значение $z на слова, превращая все пробелы (пробелы, табуляции, новые строки) в разрывы слов. Если это произойдет, eval получит слова "echo "" a ""echo " b", эффективно превращая новую строку в пробел:
$ eval $z
a echo b

Это еще один случай в длинном списке случаев, когда важно дважды цитировать ссылки на переменные.

Вы передаете новую строку в eval. Так что это похоже на то, как вы на консоли набираете это:

el@voyager$ echo a\necho b
anecho b

Таким образом, первый echo понимается правильно, и он думает, что вы хотите кавычки вокруг остальных. Обратная косая черта, кажется, игнорируется. Возможно, вы имели в виду что-то вроде этого:

el@voyager$ echo -e 'a\n'; echo b
a

b

Вариант 1:

Разделите операторы, переданные в eval, точкой с запятой, как это:

x='echo a'
y='echo b'
z="$x;$y"
eval $x
eval $y
eval $z

Отпечатки пальцев:

a
b
a
b

Вариант 2:

Поместите новую строку в поле место, где оно будет интерпретировано эхом, вот так:

x='echo -e "a\n"'
y='echo b'
z="$x;$y"
eval $x
eval $y
eval $z

Отпечатки пальцев:

a

b
a

b
Теперь новая строка сохраняется и интерпретируется эхом, а не эвалом.

Не обязательно оптимальный способ, так как он потерпит неудачу, если переменные x и y содержат последовательности, обработанные printf, такие как %s и подобные, но в любом случае, вот способ сделать это, сохраняя \n в качестве разделителя:

x='echo a'
y='echo b'
z="$x\n$y"
eval $x
eval $y
export IFS=" "
eval $(printf "$z")

Отпечатки пальцев:

a
b
a
b

На моей коробке FreeBSD я пытался сделать что - то в сценарии Борна, который сначала казался довольно тривиальным, но на несколько мгновений затуманил мой разум. Поскольку эта страница-то, на что я ссылался, пытаясь решить свою проблему, я объясню, что мне нужно было сделать и как я это сделал:

a=A

b=B

eval ${a}_${b}="something"

Пока никаких проблем. Я получаю новую переменную A_B, которая хранит"что-то"

Но если я распределю задание по 2 строкам, как показано ниже:

eval ${a}_${b}="some

thing"

Раковина рявкает мне в ответ, что она не может найти никакого команда называется "вещь". Важно понимать, что eval пытается оценить RHS как команду. Чтобы получить eval для оценки RHS как строки, вам нужно дважды-дважды процитировать RHS:

eval ${a}_${b}="\"some

thing\""

Надеюсь, это кому-то поможет. Маниш Джайн

Comments

    Ничего не найдено.