Bash:使用 set 和 eval 保留空格
发表于 2008 年 11 月 5 日
如果您不太关心空格,那么 Bash 是个不错的选择:它通常会将多个空格字符转换为一个空格,并根据空格将内容分解为单词。但另一方面,如果您想保留空格,Bash 在某些时候可能会有点困难。一个经常有帮助的技巧是结合使用 Bash 的eval和set命令。
假设您正在构建一个项目列表,其中每个项目可能包含重要的空格,比如类似这样的:
#!/bin/bash
items=
for i in "$@"
do
items="$items \"$i\""
done
for i in $items
do
echo $i
done
但是,当您运行它并尝试使用保存列表中的项目时,您并没有得到您期望的结果
$ sh t1.sh "ab cd" "ef gh" "ab cd" "ef gh"
一种解决方案是执行以下操作
#!/bin/bash
items=
for i in "$@"
do
items="$items \"$i\""
done
eval set -- $items
for i in "$@"
do
echo $i
done
这会产生期望的结果
$ sh t2.sh "ab cd" "ef gh" ab cd ef gh
重要的行是
eval set -- $items
这个set命令获取选项之后的任何参数(此处 "--" 表示选项的结束),并将它们分配给位置参数 ($0..$n)。eval命令将其参数作为 bash 命令执行。
如果您在没有eval命令的情况下执行此操作,您将得到与第一个示例相同的结果。通过将set命令传递给evalBash,Bash 将尊重字符串中的嵌入式引号,而不是假定它们是单词的一部分。
如果您运行此脚本,您可以看到更多 Bash 正在执行的操作
#!/bin/bash
items=
for i in "$@"
do
items="$items \"$i\""
done
set -x
set -- $items
set +x
echo '===='
set -x
eval set -- $items
set +x
这会产生
$ sh t3.sh "ab cd" "ef gh" + set -- '"ab' 'cd"' '"ef' 'gh"' + set +x ==== + eval set -- '"ab' 'cd"' '"ef' 'gh"' ++ set -- 'ab cd' 'ef gh' + set +x