【问题标题】:'revealing' hidden/control 'codes' in strings in bash'揭示'隐藏/控制'代码'在bash中的字符串中
【发布时间】:2015-12-09 04:33:20
【问题描述】:

Python 中有一个非常方便的函数:repr(),当应用于包含空白字符的字符串时,将打印出该字符串的表示形式,不会导致对字符串实际内容的任何人为误解。

例如:

$ python -c "print repr(r'''abcde\rfghi\tjklmn\nopqr\bstuv\fwxyz''')"
'abcde\\rfghi\\tjklmn\\nopqr\\bstuv\\fwxyz'

如何在 bash 中使用 printf 做同样的事情?

我正在寻找的完美工具/技巧会真正打印出来

'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

【问题讨论】:

  • echo 确实打印了 '\r' 字符本身,而不是它的人类表示\r。所以结果只是插入符号被发送到了行首,但是,用户看不到。
  • 抱歉,不清楚 - 当我这样做时: TSTR="abcd\refjh\bijk" 然后 echo "## ${TSTR} ##" - 我得到文字输出;如果我使用'printf',是的,CR 会覆盖。这是 Linux/Bash,是吗?
  • 你是对的,它在 shell 中工作。我想在我使用printf 的软件中确实使这一切变得复杂:/
  • 尝试在字符串中使用两个 '\',即将单个 '\' 替换为 '\\' 使用工具的字符串函数。
  • 问题是我无法控制这些字符串,我只使用可能碰巧有我想要打印的空白字符的变量

标签: string bash shell quoting ansi-c


【解决方案1】:

%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"

【讨论】:

  • 太棒了,我非常喜欢这个:)
  • 是否可以强制使用 ANSI-C 引用语法?
  • 我认为没有简单的方法,但请参阅我的更新以了解一些技巧。
猜你喜欢
  • 2016-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多