SED:同一行上的多个模式,如何匹配/解析第一个模式



我有一个文件,里面有电话号码数据,还有一些无用的东西。我试着把这些号码解析出来,当每行只有一个电话号码时,这没问题。但是,当我有多个数字时,sed会匹配最后一个(尽管它在任何地方都说它应该只匹配第一个模式?),我无法获得其他数字。。

我的数据.txt:

bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla

当我解析数据时,我的想法是首先删除第一个电话号码前的所有"初始"bla-bla-bla"(所以我搜索第一个出现的"NUM:"),然后删除电话号码后的所有内容,并获得号码。之后,我想从剩余的字符串中解析下一个出现的字符串。

所以现在,当我尝试使用它时,我总是得到最后一个号码:

>sed 's/.*NUM://' data.txt
08022222222 bla bla bla
> 

首先,我想了解我对SED的理解有什么问题。当然,欢迎更有效的建议!我的sed命令不是说,用"(空)替换"NUM:"之前的所有内容吗?为什么它总是与最后一次匹配?

谢谢!

这可能对您有用:

echo "bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla" |
sed 's/NUM:/n&/g;s/[^n]*n(NUM:[0-9]*)[^n]*/1 /g;s/.$//'
NUM:09011111111 NUM:08022222222

您的问题是理解.*是贪婪的,即它匹配最长的匹配而不是第一个匹配。通过在我们感兴趣的字符串(NUM:...)前面放置一个唯一字符(n-sed将其用作行分隔符,因此它不可能存在于行中),并删除所有不是唯一字符[^n]*然后是唯一字符n的字符,我们可以有效地将字符串拆分为可管理的部分。

正如您现在所知,sed正则表达式是贪婪的,据我所知,不能使其成为非贪婪的。

到目前为止还没有提出的两种选择是使用其他工具进行这种匹配/提取。

您可以使用perl作为具有-pe参数的sed的插入式替换。它支持?非贪婪修饰符:

$ perl -pe 's/.*?NUM://' data.txt
09011111111 bla bla bla bla NUM:08022222222 bla bla bla

您可以使用GNU grep的-o选项来只获取与正则表达式匹配的数据位:

$ egrep -o 'NUM:[0-9]*' data.txt 
NUM:09011111111
NUM:08022222222

如果一个数字是由NUM::后面的数字定义的

sed -n -e 's/$/n/' -e ':begin' 
  -e 's/(NUM:[0-9][0-9]*)(.*)n(.*)/2n3 1/' 
  -e 'tbegin' -e 's/.*n //' -e '/NUM/p'

它的作用是:

  1. 将一个n放在行的末尾作为标记
  2. 试着在标记之前找到一个数字,然后把它放在行的末尾(标记之后)
  3. 如果找到一个数字,转到上面的2
  4. 如果标记之前没有数字,请删除数字之前的所有内容
  5. 如果行上有数字,请将其打印出来(以处理找不到数字的情况

也可以用另一种方法,首先删除没有数字的行:

sed  -e '/NUM/!d' -e 's/$/n/' -e ':begin' 
  -e 's/(NUM:[0-9][0-9]*)(.*)n(.*)/2n3 1/' 
  -e 'tbegin' -e 's/.*n //'

您可以使用以下模式:

sed -r 's/^(.*NUM:)(.*NUM:.*)$/2/'
sed -E 's/(-y)|(-f)|(+incdir+)/n&/g' abcfile > cdeop

其中abcfile将具有-y/-f/+incdir+模式作为示例,当模式匹配时,它将在其前面插入新行。

相关内容

  • 没有找到相关文章

最新更新