Bash:扩展变量,但不是特殊字符

时间:2014-11-16 11:54:13

标签: bash variables eval expect expand

我有一个bash脚本,它通过将包含expect代码片段的数十个不同文件拼接在一起来创建并执行expect脚本。这些文件包含需要扩展的环境变量。例如:

expect.piece:

send "command\r"
sleep $timeout
send "command argument\r"

script.sh:

#let's try it like this
eval echo $(cat expect.piece)
#or maybe like this
eval "echo \"$(cat expect.piece)\""

输出:

send command\r sleep 1 send command argument\r
send commandr
sleep 1
send command argumentr

所需的输出:

send "command\r"
sleep 1
send "command argument\r"

我需要一个没有sed字符串替换的解决方案(有很多环境变量)并且不需要修改原始的expect脚本文件。我想它可以逐行完成,但有更优雅的解决方案吗?

4 个答案:

答案 0 :(得分:0)

bash中的默认字段分隔符是space,因此在执行IFS=$(echo -e '\n')之前将输入文件分隔符设置为eval echo $(cat expect.piece)之类的新行。

最终脚本将是:

#Storing original field separator in variable OFS
OFS=$IFS
#Setting IFS as new line using echo -e. Unfortunately IFS="\n" does not work in bash
IFS=$(echo -e '\n')
eval echo $(cat expect.piece)
#Resetting the field separator as space
IFS=$OFS

答案 1 :(得分:0)

还有另一种方法可以将expect代码带有-c标记放在shell脚本中,如下所示。

<强> script.sh

#Calling the expect.piece file code here
expect -c expect.piece

您可以将可选命令行值用作

expect -c "set count 1" myscript.exp

变量count将在expect脚本文件myscript.exp中使用。

您可以直接将整个代码作为

expect -c "
             send \"command\r\"
             sleep $timeout
             send \"command argument\r\"
"

注意在需要的地方使用反斜杠来转义双引号。也可以使用单引号。但是,如果你使用双引号,那么只能进行shell替换。

请参阅here了解-cexpect标志的详情。

答案 2 :(得分:0)

从您的问题中不清楚您想要此输出的上下文。如果可以将Expect脚本作为here文档嵌入,那么你想要的是微不足道的。

#!/bin/sh

timeout=1

cat <<____HERE
send "command\r"
sleep $timeout
send "command argument\r"
____HERE

(也许您甚至可以将cat替换为expect,但我对Expect不够熟悉,无法提出任何建议。)

如果您需要从文件中获取输入,并且只需要扩展一组有限的变量,则可以使用sed执行此操作。

sed "s/\$timeout/$timeout/g" file

如果您需要更通用的解决方案,可能需要切换到Perl:

perl -pe 's/\$(\w+)/$ENV{$1} || "\$$1" /ge' file

但是这需要您export(或以其他方式向Perl公开)您想要导出的shell环境变量。 (这不会替换任何未定义的变量;如果要更改行为的这一方面,请更改||之后的值。)

答案 3 :(得分:0)

我发明了这个问题的解决方案,它是一个kludge,但它的确有效。

expect.piece:

sleep $timeout
send "foo bar\r"
send "$(date)\r"

script.sh:

timeout=1
eval echo $(sed " \
s/\\\/\\\\\\\/g; \
s/\"/\\\\\"/g; \
s/\"/\\\\\`/\"/\\\\\`/g; \
" "expect.piece" | tr '\n' '+') | tr '+' '\n'

输出:

sleep 1
send "foo bar\r"
send "Wed Feb 18 03:19:24  2015\r"

首先,我们需要转义文件中的所有反斜杠,反引号和引号,因为它们将在评估期间被删除。然后,我们需要用加号替换所有换行符,以便将它组成一行。之后,我们评估该行(评估将&#34;扩展&#34;所有环境变量和命令替换)并将更新替换回换行。