比较Bash中的特殊字符

时间:2015-08-10 18:20:54

标签: bash

我有一个我写的函数,输出这样的彩色输出类型:

foo() {
  local arrow="\033[1;32m↑\033[0m"
  echo "1$arrow"
}

我想测试这个函数,所以我正在使用https://github.com/kward/shunit2对它进行单元测试。

test_foo() {
  local green_arrow="\033[1;32m↑\033[0m"
  assertEquals "1$green_arrow" "$(foo)"
}

但是shunit抱怨说:ASSERT:expected:< 1↑> but was:< 1↑>。我猜这个函数输出隐藏字符有问题。

有没有办法去掉特殊字符,或者从变量中删除它们?

编辑:

运行以下命令显示\\033转义字符正在被回显转换为文字\E转义符:

printf '%q' "1$green_arrow"
' 1\\033[1;32m?\206\221\\033[0m'

printf '%q' "$(foo)"
' 1\E[1;32m?\206\221\E[0m'

1 个答案:

答案 0 :(得分:4)

使用printf -v varname_quoted %q "$varname"获取内容的转义形式将提供一种易于阅读且易于理解的表单,该表单也可以作为文字包含在您的代码中,无需额外引用或转义需要。 (如果你的目标是将引用的内容发送到stdout而不是另一个变量),这可以简化为printf %q "$varname"

也就是说,要将格式字符串转换为文字(支持参数的格式字符串,即。%s%02f等):

printf -v green_arrow '\033[1;32m↑\033[0m'

...或者,反斜杠转义字符串(仅支持完整格式字符串语法的子集)到文字:

printf -v green_arrow '%b' '\033[1;32m↑\033[0m'

...然后,以逃逸的,人类可读的形式发出该文字,以便于比较和/或复制并粘贴到shell脚本中作为文字:

printf '%q\n' "$green_arrow"

将所有这些结合在一起,以下是获取更易读的错误消息的一种方法(请原谅StackOverflow的语法突出显示,在撰写本文时,并未完全了解嵌套引用上下文在bash中的工作方式):

test_foo() {
  local green_arrow=$'\E[1;32m↑\E[0m'
  assertEquals "$(printf '%q' " 1$green_arrow")" "$(printf '%q' "$(foo)")"
}

...或者,更有效率(避免不必要的子壳):

test_foo() {
  local green_arrow=$'\E[1;32m↑\E[0m'
  local desired_answer_quoted actual_answer_quoted
  printf -v desired_answer_quoted '%q' " 1$green_arrow"
  printf -v actual_answer_quoted  '%q' "$(foo)"
  assertEquals "$desired_answer_quoted" "$actual_answer_quoted"
}