“结尾处的换行符”$"("")";在shell脚本中删除。为什么?
有人能解释为什么这两个命令的输出不同吗“结尾处的换行符”$"("")";在shell脚本中删除。为什么?,shell,unix,scripting,ksh,Shell,Unix,Scripting,Ksh,有人能解释为什么这两个命令的输出不同吗 $ echo "NewLine1\nNewLine2\n" NewLine1 NewLine2 <-- Note 2nd newline here $ echo "$(echo "NewLine1\nNewLine2\n")" NewLine1 NewLine2 $ <-- No second newline $echo“NewLine1\nNew
$ echo "NewLine1\nNewLine2\n"
NewLine1
NewLine2
<-- Note 2nd newline here
$ echo "$(echo "NewLine1\nNewLine2\n")"
NewLine1
NewLine2
$ <-- No second newline
$echo“NewLine1\nNewLine2\n”
新闻1
新闻2
命令替换将删除每一个后续换行符
删除一个是有道理的。例如:
basename foo/bar
输出条\n
。在:
var=$(basename foo/bar)
您希望$var
包含bar
,而不是bar\n
然而在
var=$(basename $'foo/bar\n')
您希望$var
包含bar\n
(毕竟,换行符与Unix上文件名中的任何字符一样有效)。但是,所有shell都会删除所有尾随的换行符。这一缺陷出现在原来的伯恩外壳中,甚至修复了伯恩大部分缺陷的rc
也没有修复该缺陷。(尽管rc
具有``({cmd}
语法,不去除任何换行符)
在POSIX Shell中,要解决此问题,可以执行以下操作:
var=$(basename -- "$file"; echo .)
var=${var%??}
尽管您将失去basename
的退出状态。您可以通过以下方式进行修复:
var=$(basename -- "$file" && echo .) && var=${var%??}
${var%??}
将删除最后两个字符。第一个是我们在上面添加的
,第二个是由basename
添加的一个换行符,我们不再删除任何换行符,因为其他换行符(如果有的话)将是我们想要获取其基的文件名的一部分,所以我们确实需要它们
在没有${var%x}
运算符的Bourne shell中,您必须以一种漫长而复杂的方式来解决它。因为并且一直都像在Bourne shell中一样:
2.6.3命令替换
命令替换允许替换命令的输出
代替命令名本身。命令替换应发生
当命令按如下方式封闭时:
$(命令)
或(后引版本):
`命令`
shell应通过执行命令扩展命令替换
在子Shell环境中(请参见Shell执行环境)和
替换命令替换(命令文本加上
将“$()”或反引号)与
命令,在指定位置删除一个或多个字符的序列
替换结束。在结尾之前嵌入字符
不应移除输出的任何部分;但是,它们可能被视为
字段分隔符,并在字段拆分期间消除,具体取决于
有效的IFS值和引用。如果输出包含
任何空字节,行为都是未指定的
保留最后换行的一种方法是
视觉:
$x=“$(whoami;echo x)”;printf'\n'$x'${x%x}”
但为什么要删除尾随的新行呢?因为很多时候你都希望这样。我也在用perl编程,我无法计算读取一行或一个变量然后需要切掉换行符的次数:
while (defined ($string = <>)) {
chop $string;
frobnitz($string);
}
while(已定义($string=)){
切掉$string;
弗罗布尼茨($string);
}
如果没有删除换行符,则构造如下:
x="$(pwd)/filename"
不会有效地工作,但编写Unix的人更喜欢有用的行为
很长一段时间以前(比如1983年,也许1984年),有一次,我在Unix的一个特定变体上遇到了一个shell更新,它没有删除后面的换行符。它破坏了所有地方的脚本。它很快就被修复了。回声的本质是消耗空白。我现在没有时间进行测试,但您在问题测试中引用的dbl可能没有达到您的想法。也许echo“$(echo\'NewLine1\nNewLine2\n\””
会起作用。祝您好运。谢谢,但您不需要在“$(..”语句的括号内转义双引号。它被视为一个新命令。这是使用$(…)而不是滴答声的优点之一。上面的问题也可以通过使用记号来重现。它的记录行为:()-“…命令的标准输出,删除任何尾随的换行符”。为了避免这种情况,您可能需要将输出重定向到临时文件,然后使用该文件。这是一个很好的解释。这有点令人沮丧,因为我有一个脚本,其中“$(…)”语句末尾的新行对我很重要。就像我上面所说的,我可能会附加一个随机字母,然后将其去掉。@glennjackman:您应该将其作为答案发布。VAR=“$(command)x”
不会保留最后的换行符,因为是命令替换将其去掉。@sch Oops,已修复。谢谢你的提醒。
while (defined ($string = <>)) {
chop $string;
frobnitz($string);
}
x="$(pwd)/filename"