首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >找出反复出现的模式与“轿车”

找出反复出现的模式与“轿车”
EN

Stack Overflow用户
提问于 2021-11-03 17:55:01
回答 5查看 190关注 0票数 3

我正在使用GNU bash 4.3.48

我本以为

代码语言:javascript
代码运行次数:0
运行
复制
echo "23S62M1I19M2D" | sed 's/.*\([0-9]*M\).*/\1/g'

将输出62M19M.但事实并非如此。

sed 's/\([0-9]*M\)//g'删除所有[0-9]*M并检索23S1I2D。但\1小组并没有像我想象的那样工作。

sed 's/.*\([0-9]*M\).*/ \1 /g'检索M.

我做错了什么?

谢谢!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2021-11-03 18:14:53

问题是.*是贪婪的。由于只有M是必需的,所以当引擎找到最后一个M时,它满足正则表达式,所以所有字符串都匹配,因此在用\1反向引用替换之后,捕获并保存了M

这意味着,使用sed很难做到这一点。使用Perl可以更容易地做到这一点,因为它支持匹配和跳过模式:

代码语言:javascript
代码运行次数:0
运行
复制
#!/bin/bash
perl -pe 's/\d+M(*SKIP)(*F)|.//g' <<< "23S62M1I19M2D"

在线演示。模式匹配

  • \d+M(*SKIP)(*F) -一个或多个数字,M,然后省略匹配,然后从失败位置搜索下一个匹配。
  • |. -或匹配除换行字符以外的任何字符。

或者简单地匹配所有的事件并将它们连接起来:

代码语言:javascript
代码运行次数:0
运行
复制
perl -lane 'BEGIN{$a="";} while (/\d+M/g) {$a .= $&} END{print $a;}' <<< "23S62M1I19M2D"

所有\d+M匹配都附加到$a变量,该变量在处理字符串结束时打印。

票数 1
EN

Stack Overflow用户

发布于 2021-11-03 19:22:49

使用显示的示例和awk,您可以尝试执行以下程序。

代码语言:javascript
代码运行次数:0
运行
复制
echo "23S62M1I19M2D" | 
awk '
{
  val=""
  while(match($0,/[0-9]+M/)){
    val=val substr($0,RSTART,RLENGTH)
    $0=substr($0,RSTART+RLENGTH)
  }
  print val
}
'

解释:的简单解释将是,使用echo打印值并将其作为标准输入发送到awk程序。在awk程序中,使用它的match函数来匹配它(/[0-9]+M)中提到的正则表达式,运行循环查找每一行中的所有匹配值,并在每一行的最后打印所收集的匹配值。

票数 2
EN

Stack Overflow用户

发布于 2021-11-03 19:26:54

这可能对您有用(GNU sed):

代码语言:javascript
代码运行次数:0
运行
复制
sed -nE '/[0-9]*M/{s//\n&\n/g;s/(^|\n)[^\n]*\n?//gp}' file

用换行符包围匹配,然后删除不匹配的部分。

备选办法,使用grep和tr:

代码语言:javascript
代码运行次数:0
运行
复制
grep -o '[0-9]*M' file | tr -d '\n' 

注意:tr删除所有换行符(包括最后一行)以恢复最后一个换行符,请使用:

代码语言:javascript
代码运行次数:0
运行
复制
grep -o '[0-9]*M' file | tr -d '\n' | paste  

替代解决方案将将所有结果连接到一行中。要实现第一个解决方案的相同结果,请使用:

代码语言:javascript
代码运行次数:0
运行
复制
sed -nE '/[0-9]*M/{s//\n&\n/g;s/(^|\n)[^\n]*\n?//g;H};${x;s/\n//gp}' file
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69829591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档