tr命令:与...的奇怪行为和\

时间:2018-05-07 20:30:10

标签: bash escaping pipe translate tr

假设我有一个带有内容的文件test.txt:

+-foo.bar:2.4
|    bar.foo:1.1:test
\|  hello.goobye:3.3.3
   \|+- baz.yeah:4

我想使用tr命令删除以下字符集的所有实例:

{' ', '+', '-', '|', '\'}

对此进行了一些非常广泛的研究,但没有找到明确/简明的答案。 这是有效的命令:

输入:

cat test.txt | tr -d "[:blank:]|\\\+-"

输出:

foo.bar:2.4
bar.foo:1.1:test
hello.goobye:3.3.3
baz.yeah:4

我尝试了该组的许多组合,我发现' - '被视为范围指示器(如... [a-z]),因此必须放在最后。但我有两个主要问题:

1)为什么反斜杠必须双重转义才能被包含在集合中?

2)为什么要放'|'在set字符串的末尾导致tr程序删除文件中的所有内容,除了尾随换行符号?

2 个答案:

答案 0 :(得分:3)

像这样:

tr -d '\-|\\+[:blank:] ' < file

您必须转义-,因为它用于表示字符范围,如:

tr -d '1-5'

因此如果你的意思是字面连字符,必须进行转义。你也可以把它放在最后。 (了解到,谢谢!:))

此外,\必须转义为文字\,因为它具有转义序列所需的特殊含义。

其余字符不得转义。

为什么\必须在你的例子中被双重逃脱?

这是因为您使用""(双引号)字符串来引用char集。双引号字符串将由shell解释,双引号字符串中的\\表示文字\。尝试:

echo "\+"
echo "\\+"
echo "\\\+"

为避免双重逃避\,您可以使用单引号,如上例所示。

为什么选择&#39; |&#39;在set字符串的末尾导致tr程序删除文件中的所有内容,除了尾随换行符号?

CharlesDuffy's comment结尾处|意味着您还没有未转义的-,这意味着它描述了实际范围取决于的一系列字符在你在集合中的位置。

答案 1 :(得分:2)

另一种方法是定义允许的字符

$ tr -cd '[:alnum:]:.\n' <file

foo.bar:2.4
bar.foo:1.1:test
hello.goobye:3.3.3
baz.yeah:4

或者,也许删除所有前缀非单词字符

$ sed -E 's/\W+//' file