Как разделить несколько команд, переданных 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)?
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