2011-08-01 29 views
2

经过几个小时的与脚本交战之后,我将问题缩小到了下面的范围。在命令提示符下运行这个(庆典),以显示该问题:涉及sed和反引号的shell脚本怪异

bash$ echo "\n" 
\n 
bash$ echo "\n" | sed 's/\\n/---\\&/g' 
---\\n 
bash$ str=`echo "\n" | sed 's/\\n/---\\&/g'` 
bash$ echo $str 
\n 
bash$ 

我不明白为什么海峡= ...命令并不等同于海峡=在...命令的输出。

为什么它不等于str =“--- \ n”?

我必须在这里丢失一些基本的东西。

编辑:在回应评论:

$ /bin/bash --version 
GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu) 
Copyright (C) 2011 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 

This is free software; you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. 

还,解决方案不是简单的答案,说明只有在反引号返回管道的第一部分。
注意:

bash$ str=`echo "abc" | sed 's/a/---&/g'` 
bash$ echo $str 
---abc 
bash$ 

所以不知它是事物包括\这是造成问题的字符的组合。我无法弄清楚这里的行为。

回答

2

其他答案可能是正确的关于一些报价被丢弃。我最近学到的技巧是使用$()而不是反引号。

str=$(echo "\n" | sed 's/\\n/---\\&/g') 

按预期工作。


更新

这里是如何似乎工作。首先考虑这个例子:

$ echo "\\n" 
\n 
$ echo '\\n' 
\\n 

在shell中有强和弱的引用。弱报价以“(双引号)”表示,强引用以“(单引号)”表示,弱报不能防止转义,强转会阻止转义,而反斜杠的含义为preserving next character except newline,所以“\\ n”是实际上等于两个字符:。\n因为第一斜线逃脱其上印强的报价,而另一方面,也不会做任何逃避和“\\ N”变成三个大字\\n

弱引号的另一个性质是它们阻止强引号生效并使其被字面解释。

因此,现在考虑例如e类似于您的sed示例:

$ echo `echo '\\n'` 
\n 

那么这里会发生什么?后面的嘀嗒声被处理为弱报价,这是强烈的报价,停止做任何报价。所以'\\ n'会被解释为'\ n',因为\会被转义。因此,执行的命令是echo '\n'而不是echo '\\\\n'。这正是你所发生的情况sed

真棒问题,真的让我思考和研究它。

+0

谢谢。我仍然想知道发生了什么,但是这个提示(以及将读取命令更改为读取-r)修复了我的脚本。谢谢! – CuriousJackie

+0

好的,我添加了解释。 –

0

它的工作原理,如果你这样做

str=`echo "\n" | sed 's/\\\\n/---\\\\&/g'` 

我的猜测是,一个引用在这样的嵌套正在消失,但我很乐意听到更多的背景...

+0

如果是这种情况,回声“\ n”会变成回声“n”或其他东西。没有? – CuriousJackie

+0

正如我所说:我很想理解这种行为(错误?)我自己。 – mkro

+0

追踪您的想法。对单引号引用echo的引用不会改变,删除引号只会让我们输出“n”。将sed引号更改为双引号并不会改变任何内容*,但删除引号会给出带有---的输出*!但仍不如预期。奇怪的。我认为你正在尝试一些东西。 – CuriousJackie