如何在Awk中使用单个正则表达式提取多个字符串

如何在Awk中使用单个正则表达式提取多个字符串,awk,Awk,我有以下字符串: Mike has XXX cats and XXXXX dogs. MikehasXXXcatsandXXXXXdogs 我想将Xs替换为对应于Xs数量的数字: 我试过: awk '{ match($0, /[X]+/); a = length(substr($0, RSTART, RLENGTH)); gsub(/[X]+/, a) }1' 但它只捕捉到了第一场比赛 预期产出: Mike has 3 cats and 5 dogs. Mikehas3catsand

我有以下字符串:

Mike has XXX cats and XXXXX dogs.
MikehasXXXcatsandXXXXXdogs
我想将Xs替换为对应于Xs数量的数字:

我试过:

awk '{ match($0, /[X]+/);
  a = length(substr($0, RSTART, RLENGTH));
  gsub(/[X]+/, a) }1'
但它只捕捉到了第一场比赛

预期产出:

Mike has 3 cats and 5 dogs.
Mikehas3catsand5dogs

有了你们展示的样品,你们能试一下下面的吗。用GNU
awk
编写和测试(应适用于任何
awk

说明:检查所有字段(以空格分隔),检查字段是否从
X
开始,并且在当前字段结束之前只有
X
,如果是,则用其自身的值全局替换它(以获得计数),并保存到当前字段本身。然后1将打印当前行



注意:根据Ed sir的评论(在问题部分下),如果您的字段可能也有其他
X
值,请尝试(这甚至包括任何列中的
XXX456
值):

上述代码的输出如下所示:

Mike has 3 cats and 5 dogs.
Mikehas3catsand5dogs

另一个
awk

$ awk '{for(i=1;i<=NF;i++) if($i~/^X+$/) $i=length($i)}1' file

Mike has 3 cats and 5 dogs.
$awk'{for(i=1;i如果Perl可以:

$perl-pe's/X+/length$&/ge'ip.txt
迈克有3只猫和5只狗。
Mikehas3猫5狗

e
标志允许在替换部分使用Perl代码。
$&
将有匹配的部分。

这是我能想到的最干净的基于awk的解决方案

 {mawk/mawk2/gawk} 'BEGIN { FS = "^$" } /X/ { 

      while(match($0, /[X]+/)) { sub(/[X]+/, RLENGTH) } } 1'

缺点是每次重播都必须使用两次正则表达式引擎。优点是它避免了大量的
substr()
ops。

太棒了,谢谢!@LechKaczmarczyk,你可以看到这个链接,欢呼和愉快的学习。你也可以使用
length(RT)
而不是
gsub
作为最后一个解决方案好的一点!
MikehasXXXcatsanXXXXXdogs
将更接近我需要它的目的。但是我更感兴趣的是解决问题的一般方法,而不是细节。@LechKaczmarczyk,哦,因为您的样本已经更改,所以现在我们需要(我和karafka先生)我们也需要改变我们的方法。这是一个很好的要求,把Ed sir提到的样本放在第一位,这样以后就不会有困惑,干杯,愉快的学习如果这里的任何答案解决了你的问题,那么看看下一步该怎么办。如果没有,那么在答案下以评论的形式提问你觉得这是最接近的。它会比awk快吗?这是更复杂的文本处理管道中的一个步骤,我认为将所有内容包装在一个awk脚本中会更有效。Perl通常比awk慢,但在这种情况下它可能会更快,不能肯定没有评测。如果awk脚本中已经有其他内容,我会比如说,坚持使用该解决方案,而不是awk+perl的组合。
awk -v RS='X+' '{ORS=(RT ? gsub(/./,"",RT) : "")} 1' Input_file
awk -v RS='X+' '{ORS=(RT ? length(RT) : "")} 1' Input_file
Mike has 3 cats and 5 dogs.
Mikehas3catsand5dogs
$ awk '{for(i=1;i<=NF;i++) if($i~/^X+$/) $i=length($i)}1' file

Mike has 3 cats and 5 dogs.
$ awk '{while( match($0,/X+/) ) $0=substr($0,1,RSTART-1) RLENGTH substr($0,RSTART+RLENGTH)} 1' file
Mike has 3 cats and 5 dogs.
Mikehas3catsand5dogs
 {mawk/mawk2/gawk} 'BEGIN { FS = "^$" } /X/ { 

      while(match($0, /[X]+/)) { sub(/[X]+/, RLENGTH) } } 1'