给定一个这样的文件:
x y y z x
x x y z z y
x x x z y
y z z y x x x
x x x x x
我希望输出是:
x y+ z x
x+ y z+ y
x+ z y
y z+ y x+
x+
这可以用 awk 或 perl 来做吗?即是否可以在行中找到任意数量的相似值并将它们合并?
答案1
sed 's/\(.\)\( \1\)\{1,\}/\1+/g' <in >out
x y+ z x
x+ y z+ y
x+ z y
y z+ y x+
x+
使用 BSD 或 GNU sed
:
sed -Ee's/(.)( \1)+/\1+/g' <in >out
要使用任意字段长度,您只需使用任意字段长度即可:
sed -Ee 's/(...)( \1)+/\1+/g' <<""
xxx yyy yyy zzz xxx
xxx xxx yyy zzz zzz yyy
xxx xxx xxx zzz yyy
yyy zzz zzz yyy xxx xxx xxx
xxx xxx xxx xxx xxx
xxx yyy+ zzz xxx
xxx+ yyy zzz+ yyy
xxx+ zzz yyy
yyy zzz+ yyy xxx+
xxx+
或者在第二行中稍微修改@terdon的输入:
sed -Ee's/(([^ ]+ *)+)( +\1)+/<\1>+/g' <<""
foo foo foo bar foo
bar foo bar foo
foo foo x x x bar
<foo>+ bar foo
<bar foo>+
<foo>+ <x>+ bar
答案2
该perl
版本还可以处理任意字段长度,而不仅仅是单个字符的字段长度:
$ perl -lpae 'for $i (@F){s/($i\s*){2,}/$i+ /g}' file
x y+ z x
x+ y z+ y
x+ z y
y z+ y x+
x+
在更复杂的文件上:
$ cat file
foo foo foo bar foo
bar foo bar bar foo
foo foo x x x bar
$ perl -lpae 'for $i (@F){s/($i\s*){2,}/$i+ /g}' file
foo+ bar foo
bar foo bar+ foo
foo+ x+ bar
解释
修剪-l
每个输入行中的换行符,将-a
空白上的输入字段拆分到数组中@F
,并-p
在应用 给出的脚本后打印每个输入行-e
。
脚本本身迭代每个输入字段(数组@F
),将每个字段保存为$i
.替换查找 2 个或更多连续的$i
0 个或多个空格,并将它们替换为$i+
。