Text1 Text2
(3 tabs) text 3
(4 tabs) text 4
(2 tabs) text 5
Text2 Text7
(2 tabs) Text8
我有一个上述格式的文本文件。基本上我想做的是,我想用一个特殊的char替换连续的换行符和制表符。我正在使用此命令
tr '\n\t+' '@'
我期待这个输出
Text1 Text2@text 3@text 4@text 5<br/>
Text2 Text7@Text8
这个正则表达式可以正常使用eclipse查找和替换(也可以使用editplus)。但是tr
将所有内容放在一行中。
任何人都可以通过此正则表达式告诉我tr
的问题是什么?而且,决议是什么?
答案 0 :(得分:3)
这是tr
命令的错误使用。它允许您将一个字符(类)翻译为另一个字符(类),但不能将其用于此类正则表字符串替换。
您可以改为使用gnu sed
:
sed ':a;N;$!ba;s/\n\t\+/@/g;' file
Text1 Text2@text 3@text 4@text 5
Text2 Text7@text8
此sed命令有两部分:
:a;N;$!ba;
:通过N
命令将当前和下一行追加到模式空间(这是一个在应用字符串替换之前预先读取整个输入的循环)s/\n\t\+/@/g;
按@
编辑:以下是适用于OSX的非gnu sed 版本:
sed -e ':a' -e 'N' -e '$!ba' -e $'s/\\n\t\t*/@/g' file
答案 1 :(得分:1)
@anubhava's helpful answer解释了为什么tr
在这里不起作用,但纯sed
解决方案有一点点缺点(除了有点难以理解):它在执行所需的字符串替换之前,将整个输入文件读入内存(对于较小的文件,这可能非常好)。
如果您:
awk
或mawk
awk
和sed
这是一个解决方案,无法一次性读取整个输入:
awk -v RS='\n\t+' -v ORS=@ '1' file | sed '$d'
-v RS='\n\t+'
分配给RS
,即[输入]记录分隔符,它根据分隔换行后跟至少1个空格将输入(可能跨行)分成记录。请注意,它使用正则表达式作为不符合POSIX的记录分隔符,因此需要GNU awk
或mawk
。-v ORS=@
将@
分配给变量ORS
,即输出记录分隔符。1
构成了整个awk
程序:它是一个与{print}
实际上相同的常用快捷方式,即它只输出每个输入记录,然后是{ {1}},输出记录分隔符。ORS
终止,因此我们最终会在ORS
结束时输出,这是不受欢迎的。\n@
只是从输出中删除最后一行(sed '$d'
与最后一行匹配,$
删除它。)