如何提取字符串中da-与.之间的内容?已尝试sed、grep命令
提取
da-与.之间内容的正确方法 看起来你之前尝试的命令因为贪婪匹配或者正则写法问题没得到预期结果,我来帮你搞定这个需求。
首先,先明确你的目标:从下面这个字符串里提取da-之后到第一个.之前的内容,也就是string0和string1:
random adsf 845 asdsf.$Ecdda-string0.rand me39 84abd dee rand a[s% 845 a1sEdsf.$cdNda-string1.rand me39 84abd
为什么之前的命令失败了?
- 你的sed命令
sed -e 's/.*da-\(.*\)./\1/' file:.*是贪婪匹配,会从第一个da-一直匹配到最后一个.之前的所有内容,而且后面的.没转义,会匹配任意字符,结果肯定不对。 - 第二个grep命令
grep -o -P '(?<=da-).*(?=.)':(?=.)是匹配任意字符之前,不是匹配.之前,完全搞错了匹配目标。 - 第三个grep命令
grep -o -P '(?<=da-).*(?=\.)':还是用了贪婪的.*,会把da-之后到最后一个.之间的所有内容都抓出来,而不是每个da-对应最近的那个.。
正确的解决方案
1. 最直观的:GNU grep(PCRE模式)
用非贪婪匹配.*?代替贪婪的.*,这样就能匹配到第一个.为止:
grep -o -P '(?<=da-).*?(?=\.)' file
-o:只输出匹配到的部分,不会打印整行-P:启用Perl兼容正则,支持正向预查和非贪婪匹配(?<=da-):确保匹配内容的前面是da-(不会包含da-在结果里).*?:非贪婪匹配任意字符,找到第一个.就停止(?=\.):确保匹配内容的后面是.(不会包含.在结果里)
2. 用sed实现
如果不想用grep,sed也可以,这里用[^.]*匹配除了.之外的所有字符(比非贪婪匹配更高效):
sed -E 's/.*da-([^.]*)\..*/\1/g' file
如果要提取一行里的所有匹配项,可以用循环处理的sed脚本:
sed -E ':loop; s/(.*da-([^.]*)\.)/\1\n\2/; t loop; s/.*\n//; s/\n/\n/g' file
3. 用awk处理
awk通过循环查找匹配项来提取:
awk '{while(match($0, /da-[^.]*/)) { print substr($0, RSTART+3, RLENGTH-3); $0=substr($0, RSTART+RLENGTH) }}' file
解释一下:每次找到da-开头的非.字符串,就提取da-后面的部分,然后把已经处理过的内容从原字符串里删掉,继续找下一个匹配项。
测试结果
用上面的任意一个命令处理你的输入字符串,都会得到预期的输出:
string0 string1
内容的提问来源于stack exchange,提问作者achille
相关产品推荐
相关产品推荐

