'revealing' hidden/control 'codes' bash 中的字符串
'revealing' hidden/control 'codes' in strings in bash
Python 中有一个非常方便的函数:repr() 当应用于包含空白字符的字符串时,将打印出该字符串的表示形式,不会导致任何人对实际字符串的误解内容。
例如:
$ python -c "print repr(r'''abcde\rfghi\tjklmn\nopqr\bstuv\fwxyz''')"
'abcde\rfghi\tjklmn\nopqr\bstuv\fwxyz'
如何在 bash 和 printf 中做同样的事情?
我正在寻找的完美 tool/trick 字面上会打印
'abcd\refjh\bijk'
对于命令
printf "abcd\refjh\bijk" | <something>
这背后的目的是改进打印两个字符串之间差异的测试工具:
http_response_code=$(curl -s --head http://httpbin.org/ | head -1) # will put "HTTP/1.1 200 OK\r" in $http_response_code
assert_equal "HTTP/1.1 200 OK" "$http_response_code"
> failed: strings do not match
> expected: 'HTTP/1.1 200 OK'
> actual: 'HTTP/1.1 200 OK'
如您所见,当前的实现让用户一头雾水,对失败的原因十分困惑。
理想情况下,我希望得到以下输出:
> failed: strings do not match
> expected: 'HTTP/1.1 200 OK'
> actual: 'HTTP/1.1 200 OK\r'
当前尝试:
printf $'\a\b\e\E\f\n\r\t\v\\'\"' | cat -A
echo $'\a\b\e\E\f\n\r\t\v\\'\"' | cat -A | sed -r '$!{ N;s/$\n/\n/;t sub-yes;:sub-not;P;D;:sub-yes;}'
printf $'\a\b\e\E\f\n\r\t\v\\'\"' | od -c
%q
格式说明符接近您的理想输出:
$ printf '%q' "abcd\refjh\bijk"
abcd\refjh\bijk
这会输出一个与你的想法等价的字符串;例如,shell 对待 '\r'
和 \r
完全一样。另外,
$ printf '%q' $'\a\b\e\E\f\n\r\t\v\\'\"'
$'\a\b\E\E\f\n\r\t\v\\'"'
输出使用 ANSI 引用格式显示包含实际不可打印字符的字符串。
要对仅包含可打印字符的字符串强制使用 ANSI 引号,您可以将不可打印的字符添加到字符串的末尾,对其进行格式化,然后去除添加的字符。
$ var="My string"
$ printf -v var '%q' "$var"$'\n' # Add a newline
$ [[ $var =~ $\'(.*)\n\' ]] && var="$'${BASH_REMATCH[1]}'"
$ echo "$var"
Python 中有一个非常方便的函数:repr() 当应用于包含空白字符的字符串时,将打印出该字符串的表示形式,不会导致任何人对实际字符串的误解内容。
例如:
$ python -c "print repr(r'''abcde\rfghi\tjklmn\nopqr\bstuv\fwxyz''')"
'abcde\rfghi\tjklmn\nopqr\bstuv\fwxyz'
如何在 bash 和 printf 中做同样的事情?
我正在寻找的完美 tool/trick 字面上会打印
'abcd\refjh\bijk'
对于命令
printf "abcd\refjh\bijk" | <something>
这背后的目的是改进打印两个字符串之间差异的测试工具:
http_response_code=$(curl -s --head http://httpbin.org/ | head -1) # will put "HTTP/1.1 200 OK\r" in $http_response_code
assert_equal "HTTP/1.1 200 OK" "$http_response_code"
> failed: strings do not match
> expected: 'HTTP/1.1 200 OK'
> actual: 'HTTP/1.1 200 OK'
如您所见,当前的实现让用户一头雾水,对失败的原因十分困惑。
理想情况下,我希望得到以下输出:
> failed: strings do not match
> expected: 'HTTP/1.1 200 OK'
> actual: 'HTTP/1.1 200 OK\r'
当前尝试:
printf $'\a\b\e\E\f\n\r\t\v\\'\"' | cat -A
echo $'\a\b\e\E\f\n\r\t\v\\'\"' | cat -A | sed -r '$!{ N;s/$\n/\n/;t sub-yes;:sub-not;P;D;:sub-yes;}'
printf $'\a\b\e\E\f\n\r\t\v\\'\"' | od -c
%q
格式说明符接近您的理想输出:
$ printf '%q' "abcd\refjh\bijk"
abcd\refjh\bijk
这会输出一个与你的想法等价的字符串;例如,shell 对待 '\r'
和 \r
完全一样。另外,
$ printf '%q' $'\a\b\e\E\f\n\r\t\v\\'\"'
$'\a\b\E\E\f\n\r\t\v\\'"'
输出使用 ANSI 引用格式显示包含实际不可打印字符的字符串。
要对仅包含可打印字符的字符串强制使用 ANSI 引号,您可以将不可打印的字符添加到字符串的末尾,对其进行格式化,然后去除添加的字符。
$ var="My string"
$ printf -v var '%q' "$var"$'\n' # Add a newline
$ [[ $var =~ $\'(.*)\n\' ]] && var="$'${BASH_REMATCH[1]}'"
$ echo "$var"