簡體   English   中英

如何在bash中分隔傳遞給eval的多個命令

[英]How to separate multiple commands passed to eval in bash

我正在嘗試使用eval評估多行 shell 命令,但是當我嘗試使用由換行符分隔的 eval 解析變量時\\n變量未解析。

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

哪些輸出:

a
b
anecho b

最后一個命令給出了anecho b ,顯然\\n在那里被視為n 那么有沒有辦法評估多行命令(比如,用\\n分隔)?

\\n不是換行符; 它是一個轉義序列,在某些情況下會被轉換為換行符,但您還沒有在其中一種情況下使用它。 變量$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:

將換行符放在 echo 將解釋的位置,如下所示:

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

印刷:

a

b
a

b

現在換行符由回聲保留和解釋,而不是由評估。

不一定是最佳方式,因為如果xy變量包含由 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

一種稍微不同的方法:

read -r -d '' script <<'EOF'
echo a
echo b
EOF

eval "$script"

產出

a
b

解釋

  • read -r -d '' script
    • -r - 不允許反斜杠轉義任何字符
    • -d '' - 繼續直到讀取 DELIM 的第一個字符,而不是換行符(使其讀取到 EOF)
    • script - 保存結果的變量名
  • <<'EOF' - 使用沒有變量擴展的heredoc(圍繞EOF的單引號停止變量擴展)

選擇

這也可以使用$(cat <<'EOF'...EOF) ,但這種方式不會不必要地使用 cat 並且不使用子shell。

無用貓的示例:

script=$(cat <<'EOF'
echo a
echo b
EOF
)

eval "$script"

在我的 FreeBSD 機器上,我試圖在 Bourne 腳本中做一些事情,這起初看起來相當微不足道 - 但有一段時間讓我的頭腦蒙上了一層陰影。 由於這個頁面是我提到的試圖解決我的問題的頁面,我將解釋我需要做什么以及我是如何完成的:

a=A

b=B

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

到目前為止沒有問題。 我得到一個存儲“東西”的新變量 A_B

但是,如果我將作業分成 2 行,如下所示:

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

thing"

shell 對我咆哮說它找不到名為“thing”的命令。 重要的是要了解 eval 嘗試將 RHS 評估為命令。 要讓 eval 將 RHS 評估為字符串,您必須雙雙引號 RHS :

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

thing\""

希望這可以幫助某人。 馬尼什耆那教

您是否正在考慮使用更強大的 zsh 而不是 bash? 如果是這樣,您可能希望利用過程替換和 heredoc。 以下代碼的工作方式與標題類似。

source <(cat << EOF
command1
command2
EOF
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM