在破折号中打印带有反斜杠的变量

在破折号中打印带有反斜杠的变量

我的外壳是破折号。我的问题如下:

# 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

不,有很多变体echoecho不是可移植命令。

dash实际上是echo少数几个兼容 UNIX 的实现之一echo(至少在这方面;dash由于不支持多字节,因此在其他方面它不兼容支持多字节语言环境的系统)。

UNIX 规范要求

echo '\n'

输出两个换行符并

echo -e x

输出-e x<newline>.

虽然其他一些 shell,如 AT&T kshbashyash具有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 提供了%qdash 不提供的转换):

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

相关内容