将分号(';')赋值给bash中的变量

时间:2013-08-16 11:57:38

标签: shell unix sed escaping

我试图用sed在unix shell(bash)上的字符串中转义('\')分号(';')。当我直接执行它而不将值赋给变量时,它可以工作。也就是说,

$ echo "hello;" | sed 's/\([^\\]\);/\1\\;/g'
hello\;
$

但是,将上述命令分配给变量时,它似乎不起作用:

$ result=`echo "hello;" | sed 's/\([^\\]\);/\1\\;/g'`
$ 
$ echo $result
hello; 
$

知道为什么吗?

我尝试使用带引号和不带引号的值,但这没有帮助。任何线索都非常感激。

顺便说一句,我首先想到字符串末尾的分号以某种方式充当终结符,因此shell没有继续执行sed(如果这有意义)。但是,这似乎不是问题。我尝试使用不在字符串末尾的分号(介于两者之间)。我仍然看到与以前相同的结果。也就是说,

$ echo "hel;lo" | sed 's/\([^\\]\);/\1\\;/g'
hel\;lo
$
$ result=`echo "hel;lo" | sed 's/\([^\\]\);/\1\\;/g'`
$
$ echo $result
hel;lo
$

3 个答案:

答案 0 :(得分:3)

您根本不需要sed(或任何其他正则表达式引擎):

s='hello;'
echo "${s//;/\;}"

这是parameter expansion,用;替换\;

那说 - 你为什么要这样做?在大多数情况下,您不希望转义字符(这是语法)位于标量变量(数据)之内;它们只是在你将数据解析为语法(例如使用eval)时才有意义,这是出于其他原因的一个坏主意,最好避免(或以编程方式完成,如通过printf %q)。

答案 1 :(得分:1)

你需要使用四个(三个也可以)。我猜它是因为它被解释了两次,首先是命令,第二个是shell读取变量的内容:

result=`echo "hello;" | sed 's/\([^\\]\);/\1\\\\;/g'`

echo "$result"

的产率:

hello\;

答案 2 :(得分:1)

我发现使用反向标记给出一个结果(结果)并使用$(...)给出另一个结果(想要的结果)很有意思:

$ echo "hello;" | sed 's/\([^\\]\);/\1\\;/g'
hello\;
$ z1=$(echo "hello;" | sed 's/\([^\\]\);/\1\\;/g')
$ z2=`echo "hello;" | sed 's/\([^\\]\);/\1\\;/g'`
$ printf "%s\n" "$z1" "$z2"
hello\;
hello;
$

如果您需要使用现代x=$(...)表示法优先于旧x=`...`表示法的参数,可能就是这样。 shell使用back-ticks进行额外的反斜杠解释。我可以用一个调用我称之为al的shell脚本(用于'参数列表')时使用的一个程序来演示这个。您可以使用printf "%s\n"

进行模拟
$ z2=`echo "hello;" | al sed 's/\([^\\]\);/\1\\;/g'`
$ echo "$z2"
sed
s/\([^\]\);/\1\;/g
$ z1=$(echo "hello;" | al sed 's/\([^\\]\);/\1\\;/g')
$ echo "$z1"
sed
s/\([^\\]\);/\1\\;/g
$ z1=$(echo "hello;" | printf "%s\n" sed 's/\([^\\]\);/\1\\;/g')
$ echo "$z1"
sed
s/\([^\\]\);/\1\\;/g
$ 

如您所见,sed执行的脚本会有所不同,具体取决于您使用的是x=$(...)表示法还是x=`...`表示法。

s/\([^\]\);/\1\;/g            # ``
s/\([^\\]\);/\1\\;/g          # $()

摘要

使用$(...);它更容易理解。