tr 命令:奇怪的行为 |和 \

tr command: strange behavior with | and \

假设我有一个文件 test.txt,内容为:

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

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

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

对此进行了相当广泛的研究,但未找到 clear/concise 答案。 这是有效的命令:

输入:

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) 为什么把'|'在设置字符串的末尾导致 tr 程序删除文件中除尾随换行符之外的所有内容?

像这样:

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

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

tr -d '1-5'

因此,如果您指的是文字连字符,则必须进行转义。你也可以把它放在最后。 (学到了,谢谢!:) )

此外,当您指的是文字 \ 时,必须对 \ 进行转义,因为它具有转义序列所需的特殊含义。

其余字符不得转义。


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

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

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

为了避免双重转义 \ 你可以像我上面的例子一样使用单引号。


为什么放'|'在设置字符串的末尾导致 tr 程序删除文件中除尾随换行符之外的所有内容?

之后的末尾有 | 也意味着未转义的 - 不在末尾,这意味着它描述了一系列字符,其中实际范围取决于你在集合中的位置。

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

$ 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