我有一个文件,里面有电话号码数据,还有一些无用的东西。我试着把这些号码解析出来,当每行只有一个电话号码时,这没问题。但是,当我有多个数字时,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'
它的作用是:
- 将一个
n
放在行的末尾作为标记 - 试着在标记之前找到一个数字,然后把它放在行的末尾(标记之后)
- 如果找到一个数字,转到上面的2
- 如果标记之前没有数字,请删除数字之前的所有内容
- 如果行上有数字,请将其打印出来(以处理找不到数字的情况
也可以用另一种方法,首先删除没有数字的行:
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+模式作为示例,当模式匹配时,它将在其前面插入新行。