我试图用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
$
答案 0 :(得分:3)
您根本不需要sed
(或任何其他正则表达式引擎):
s='hello;'
echo "${s//;/\;}"
这是parameter expansion,用;
替换\;
。
那说 - 你为什么要这样做?在大多数情况下,您不希望转义字符(这是语法)位于标量变量(数据)之内;它们只是在你将数据解析为语法(例如使用eval)时才有意义,这是出于其他原因的一个坏主意,最好避免(或以编程方式完成,如通过printf %q
)。
答案 1 :(得分:1)
你需要使用四个(三个也可以)。我猜它是因为它被解释了两次,首先是sed命令,第二个是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 # $()
使用$(...)
;它更容易理解。