Text1 Text2
(3 tabs) text 3
(4 tabs) text 4
(2 tabs) text 5
Text2 Text7
(2 tabs) Text8
我有一个上述格式的文本文件。基本上我想做的是,我想用一个特殊字符替换连续的换行符和制表符。我正在使用这个命令
tr 'nt+' '@'
我期待这个输出
Text1 Text2@text 3@text 4@text 5<br/>
Text2 Text7@Text8
这个正则表达式可以很好地与eclipse查找和替换(也可以与editplus)一起工作。然而,tr
将所有内容放在一行中。
谁能告诉我tr
有什么问题,用这个正则表达式?分辨率是多少?
tr
命令使用错误。它允许您将一个字符(类)转换为另一个字符(类),但您不能将其用于像这样的正则表达式字符串替换。
您可以使用gnu sed
代替:
sed ':a;N;$!ba;s/nt+/@/g;' file
Text1 Text2@text 3@text 4@text 5
Text2 Text7@text8
这个sed命令有两个部分:
-
:a;N;$!ba;
:通过N
命令将当前行和下一行附加到模式空间(是一个循环,在应用字符串替换之前先读取整个输入) -
s/nt+/@/g;
用@
替换后跟一个或多个制表符的换行符
EDIT:这是一个非gnu sed版本,也可以在OSX上工作:
sed -e ':a' -e 'N' -e '$!ba' -e $'s/\ntt*/@/g' file
@anubhava的有用答案解释了为什么tr
在这里不起作用,但是纯粹的sed
解决方案有一个轻微的缺点(除了有点难以理解之外):它在执行所需的字符串替换之前将整个输入文件读入内存(这对于较小的文件来说可能完全没问题)。
- 有GNU
awk
或mawk
- 和不介意合并
awk
和sed
这里有一个解决方案,它不会一次读取整个输入:
awk -v RS='nt+' -v ORS=@ '1' file | sed '$d'
-
-v RS='nt+'
将[input]记录分隔符分配给RS
,该分隔符将输入(可能跨行)分隔为基于至少一个空格的换行符分隔的记录。请注意,使用正则表达式作为记录分隔符是不符合posix的,因此需要GNUawk
或mawk
。 -
-v ORS=@
将@
赋值给变量ORS
(输出记录分隔符)。 -
1
在这种情况下构成了整个awk
程序:它是一个与{print}
有效相同的常见快捷方式,即它只是输出每个输入记录,后面跟着输出记录分隔符ORS
。然而,由于每一个记录,包括最后一个记录,都以ORS
结束,我们最终在输出的末尾得到n@
,这是不希望的。 -
sed '$d'
简单地从输出中删除最后一行($
匹配最后一行,d
删除它)。