我的外壳是破折号。我的问题如下:
# A="abc\nde fg"
# printf "$A"
abc
de fg#
# B="abc\\nde fg"
# printf "$B"
abc
de fg#
# C="abc\\\nde fg"
# printf "$C"
abc\nde fg#
我正在使用的字符串变量既有空格,\n
也可能有其他空白字符。我想访问变量$A
而不转义\n
字符串中的。使用单引号不会将其解释为变量,而使用双引号会解释这些特殊字符。
dash 是否有内置于 shell 中的方法来执行此操作?我知道我可以将变量发送到外部程序,该程序会将字符串中转义字符的反斜杠加倍,但这感觉不对。
编辑:
我意识到我的错误,printf
但与本例无关。最初我使用的是echo
.这是我要问的一个更好的例子。下面是两个完全相同的命令序列,只是第一个在 bash 中,第二个在 dash 中:
巴什
$ cat sample.txt
abc\nde fg
some string
$ A=`cat sample.txt`
$ echo "$A"
abc\nde fg
some string
$
短跑
$ cat sample.txt
abc\nde fg
some string
$ A=`cat sample.txt`
$ echo "$A"
abc
de fg
some string
$
我想知道我是否可以让 dash 不解释\n
这个命令序列中的 。我已经使用外部命令实现了解决方法。正确使用printf
可以达到我想要的效果,但我很好奇破折号外壳本身是否有某种方法可以做到这一点。
为了完整起见,这就是提出问题的原因。我需要读取文件并有条件地注释或取消注释底部部分。第一部分有一个文字\n
(不是换行符),需要在重写的文件中保持这种状态。
我使用 sed 将文件分成两部分,并用反引号括起来,并将它们分配给变量。最后,我通过简单地执行类似"$VAR1$VAR2"
, where$VAR2
已被有条件注释、未注释或单独保留的操作来连接变量。
答案1
不,有很多变体echo
。echo
不是可移植命令。
dash
实际上是echo
少数几个兼容 UNIX 的实现之一echo
(至少在这方面;dash
由于不支持多字节,因此在其他方面它不兼容支持多字节语言环境的系统)。
UNIX 规范要求
echo '\n'
输出两个换行符并
echo -e x
输出-e x<newline>
.
虽然其他一些 shell,如 AT&T ksh
、bash
或yash
具有zsh
更改其内置命令的行为的设置echo
(GNU 命令的行为echo
也可能受到环境的影响),但目前dash
.
无论如何,您不想用来echo
输出任意数据。标准且可移植的命令是printf
.
您可以找到更多详细信息,包括如何在 at 的答案中实现不同的echo
包装函数printf
为什么 printf 比 echo 更好?
答案2
您的问题是 Bash 和 Dash 都有echo
内置函数,但是当给定包含以下内容的字符串时,这两种实现的行为并不相同\
:
echo 'abc\ndef'
这会在两个 shell 上产生不同的结果。
您可以使用printf '%s\n'
;获得一致的输出虽然这也是一个内置函数,但它在两个 shell 上产生相同的输出(并非所有转换都是如此,例如 bash 提供了%q
dash 不提供的转换):
printf '%s\n' 'abc\ndef'
这会abc\ndef
在两个壳中产生。
echo
您也可以使用;的外部实现在 Linux 上,coreutils
给你 GNU echo /bin/echo
:
/bin/echo 'abc\ndef'
但请注意,这不太便携。 GNU 信息文件有这样的说法:
POSIX 不要求支持任何选项,并且表示
echo
如果任何字符串包含反斜杠或者第一个参数是 ,则 的行为是实现定义的-n
。如果可移植程序printf
需要省略尾随换行符或输出控制字符或反斜杠,则可以使用该命令。
答案3
您使用printf
变量作为格式化字符串,而不是由格式化字符串插入的值。
要么使用,要么按照预期的方式echo
使用。printf
这里有些例子:
A="abc\nde fg" B="abc\\nde fg" C="abc\\\nde fg"
echo "$A"
abc\nde fg
echo "$B"
abc\nde fg
echo "$C"
abc\\nde fg
printf "%s\n" "$A"
abc\nde fg
printf "Here is variable B: %s\n" "$B"
Here is variable B: abc\nde fg
printf "> %s <\n" "$C"
> abc\\nde fg <
\
顺便说一句,通过使用双引号字符串来解析它们并处理反斜杠字符。如果使用单引号字符串定义变量,\
则也可以保留整个字符集:
A='abc\nde fg' B='abc\\nde fg' C='abc\\\nde fg'
echo "$A"
abc\nde fg
echo "$B"
abc\\nde fg
echo "$C"
abc\\\nde fg