我正在用来echo
调试我的 shell 脚本,并且想知道如何在表单中echo
打印出新行\n
和/或回车符,以便检查字符串。这可能吗?\r
\n
\r
答案1
ksh93、zsh 或 bash 的GNU 实现printf
或printf
内置函数会执行与 类似的操作,当字符串包含控制字符时,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'
在zsh
shell 中,您还可以使用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 实用程序hexdump
(hd
简称),在 *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"