使printf打印转义的反斜杠

4

因为我需要打印可能以echo选项开头的行,所以我设计了一个使用printf来打印到终端的shell函数。如果我需要打印新行或制表符,我学会了必须使用%b而不是%s,因为printf "%s" "\n"会将文字\n直接打印到屏幕上。该函数定义如下:

my_echo () {
    printf "%b" "${1}"
}

最近,我发现尝试打印转义的转义序列比通常情况下更加复杂。命令printf "%b" "\\n"将打印一个换行符。要打印换行符的文字表示,我必须使用printf "%b" "\\\n",但是这样做需要重新编码所有其他函数和脚本来处理它。有没有办法让printf "%b" "\\n"或其他类似命令输出转义的转义序列?


1
理想的方法是将转义序列放入格式字符串中,并将其排除在数据之外。printf '%s\n' "This prints one line" -- 否则,当您尝试回显包含文字反斜杠的值时,会遇到非常糟糕的情况。 - Charles Duffy
1
@Melab - 为什么它们“需要”在数据中?也许如果您提供更多的上下文,我们就能清楚地将其识别为XY问题,并帮助您找到“更好的方法”。 - ghoti
@ghoti 我写了这个函数,因为当我需要echo能够打印任何类型的字符串时,选项处理非常麻烦,包括像-n-e这样的字符串。另一件事是,我编写了另一个函数,它使用trsed的组合来转义特殊字符(例如,将\n(换行符)更改为\\n)。 sed不能用于替换换行符,我在转义函数中遇到了问题,将类似\\n的内容变成了\\\\n(它被返回为\\n\n)。 - Melab
@Melab,总之,你的函数没有问题,除了你误解了在双引号内形成字符串时反斜杠的工作原理。你的函数并没有错;相反,你传递给它的字符串是错误的,因为它们被解析时以一种你不打算的方式进行,这是由于选择不当的双引号来包含它们造成的。 - Charles Duffy
@Melab,如果你在Python中使用print(stringvar),它将打印一个字面制表符,如果字符串原本就有一个制表符,那么这不是因为它将\t序列解释回制表符,而是因为字符串的内容本来就是一个制表符 - Charles Duffy
显示剩余14条评论
1个回答

5

答案:字面量

引用类型很重要。如果您不希望反斜杠在到达函数之前被解释,请将它们放在单引号字符串中:

printf '%b' '\\n'

根据你的要求,会打印一个单独的反斜杠后跟着一个n,没有换行符。


最佳实践回答

将转义序列放在格式字符串中,而不是数据中。因此:

my_echo() { printf '%s\n' "$*"; }
my_echo_n() { printf '%s' "$*"; }

实际上,my_echo与标准的echo行为更相似:只打印一个换行符可以通过调用不带参数的my_echo来完成;打印文字也可以通过将字面量传递给my_echo来实现:my_echo_n $'\n'将打印一个字面量换行符而无需使用任何%b

同样地,要包含一个字面制表符:

my_echo $'hello\tworld'

或者

my_echo "hello"$'\t'"world"

将转义序列放在格式化中会破坏函数的整个目的。数据必须能够包含转义序列,因为它需要能够打印任何内容,例如反斜杠、制表符和换行符。 - Melab
你甚至可以使用%s来传递字面意义的反斜杠、制表符或换行符,而不是它们的转义序列。我在答案的最后一段就演示了这一点,但如果不够清晰,我可以进一步扩展说明。 - Charles Duffy
2
printf "%s" "\n" 会将字面上的 \n 写入终端,而不是换行符。需要使用 %b 才能将 \n 解释为换行符。 - Melab
Shell在单引号内不执行替换。此外,在单引号内无法转义单引号(至少在bash中是这样)。 - Melab
@Melab,你可以在一个字符串字面量中使用多种引用方式。而在bash中,$'\''也能完美运行。 - Charles Duffy
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接