使用 echo 或 printf 将换行符和回车符打印为 \n 和 \r

使用 echo 或 printf 将换行符和回车符打印为 \n 和 \r

我正在用来echo调试我的 shell 脚本,并且想知道如何在表单中echo打印出新行\n和/或回车符,以便检查字符串。这可能吗?\r\n\r

答案1

ksh93、zsh 或 bash 的GNU 实现printfprintf内置函数会执行与 类似的操作,当字符串包含控制字符时,printf %q输出字符串就像由 ksh93 引号引用一样$'...'回车或者换行:

$ string=$'foo\rbar\n' ksh93 -c 'printf "%q\n" "$string"'
$'foo\rbar\n'
$ string=$'foo\rbar\n' zsh -c 'printf "%q\n" "$string"'
foo$'\r'bar$'\n'
$ string=$'foo\rbar\n' bash -c 'printf "%q\n" "$string"'
$'foo\rbar\n'
$ string=$'foo\rbar\n'; /usr/bin/printf "%q\n" "$string"
'foo'$'\r''bar'$'\n'

zshshell 中,您还可以使用qqqq参数扩展标志来无条件使用这些$'...'引号:

$ s1=$'\r\n' s2=foobar
$ print -rC1 -- ${(qqqq)s1} ${(qqqq)s2}
$'\r\n'
$'foobar'

答案2

使用追踪

根据您的 shell,跟踪调试可能会也可能不会以明确的方式表示不可打印的字符。

x=$(printf a\\rb)
(set -x; LC_ALL=C; : "$x")

使用支持它的 shell 中的符号产生跟踪$'…':例如 ksh、mksh 和 bash all print

+ : $'a\rb'

但其他 shell,例如 dash 和 BusyBox,只是将回车符打印到标准错误,导致终端上的输出不明确,我认为这是您想要避免的。如果可以的话,请在调试时在 bash 或 (m)ksh(或 sh 模拟模式下的 zsh)中运行脚本。

使用 printf

一些 printf 实现有一个q说明符。%q类似于%s,但以允许将输出解析回 shell 的方式引用一些字符。结果在视觉上也很明确,例如选项卡打印为\t。 GNU printf 实现还支持%q.

LC_ALL=C printf %q\\n "$x"

在 Linux 上的 dash 中,您必须使用外部 printf 实用程序:/usr/bin/printf。在BusyBox 中,此功能不可用。

通过猫的管道

许多实现cat可以以视觉方式输出非打印字符,例如制表符^I而不是一堆空格。请注意,这并不是明确的:制表符与两个字符无法区分^I

printf '%s\n' "$x" | cat -vet

十六进制转储

您可以使用十六进制转储打印输出。执行此操作的便携式方法是使用od.

$ x=$(printf a\\tc\\rb); printf %s "$x" | od -tx1'
0000000 61 09 63 0d 62
0000005

BSD 实用程序hexdumphd简称),在 *BSD 和 Debian 派生的 Linux 发行版上可用,还输出可打印字符,这更好。

$ x=$(printf a\\tc\\rb); printf %s "$x" | hd
00000000  61 09 63 0d 62                                    |a.c.b|
00000005

流行的实用程序xxd(与 Vim 一起分发,但在大多数发行版中作为单独的包提供)具有类似的输出格式。

$ x=$(printf a\\tc\\rb); printf %s "$x" | xxd -g1
00000000: 61 09 63 0d 62                                   a.c.b

艰难的路

您可以使用 sed 将所有不可打印的字符一一翻译。请注意,要制作可移植脚本,您需要实际将这些可打印字符传递给 sed。如果从 shell 脚本调用 sed,则可以使用它printf来构造 sed 脚本。下面的脚本将最常见的控制字符打印为反斜杠转义符;如果需要的话添加更多。

#!/bin/sh
export LC_ALL=C
sed_script=$(printf '
s/\\\\/\\\\\\\\/g
s/'\''/\\\\'\''/g
s/\a/\\\\a/g
s/\b/\\\\b/g
s/\t/\\\\t/g
s/\f/\\\\f/g
s/\r/\\\\r/g
s/\033/\\\\e/g
$!s/$/\\\\n/
')
quoted=$(printf %sa "$2" | sed "$sed_script" | tr -d '\n')
printf "%s=\$'%s'\n" "$1" "${quoted%a}"

用法:quoted-dump x "$x"

相关内容