Regex 如何从一行文本中提取第二个模式?
在我的问题之前,让我先说一个事实,我是在AS/400上这样做的,而IBM在保持实用程序的最新性方面真的很差劲。我想提取像/[a-zA-Z0-9]*.LIB/这样的模式,但找到第二个匹配项。看看下面两条路径的不同之处:Regex 如何从一行文本中提取第二个模式?,regex,ibm-midrange,gawk,Regex,Ibm Midrange,Gawk,在我的问题之前,让我先说一个事实,我是在AS/400上这样做的,而IBM在保持实用程序的最新性方面真的很差劲。我想提取像/[a-zA-Z0-9]*.LIB/这样的模式,但找到第二个匹配项。看看下面两条路径的不同之处: /QSYS.LIB/KDBDFC1_5.LIB/AUTNOTMAIN.PGM /DATADEV/QSYS.LIB/FPSENGDEV.LIB/AUTNOTMAIN.PGM 所以,在本例中,我想要KDBDFC1_5.LIB和FPSENGDEV.LIB,而不是QSYS.LIB 我曾
/QSYS.LIB/KDBDFC1_5.LIB/AUTNOTMAIN.PGM
/DATADEV/QSYS.LIB/FPSENGDEV.LIB/AUTNOTMAIN.PGM
所以,在本例中,我想要KDBDFC1_5.LIB和FPSENGDEV.LIB,而不是QSYS.LIB
我曾尝试将gawk与match函数一起使用,并将匹配项存储在数组中,但似乎无法使用第三个参数match match不能有3个参数。我们的gawk版本是3.0.3。是 啊我在玩弄perl,试图在命令行设置中实现这一点。我们的perl版本是5.8.7。如果你的答案包含了GRIP中的一些新的新选项,你也可以考虑GRP版本的QSH版本一样旧,尽管有PASE实用程序,如果你知道那些是什么。
我仍在努力做这件事,但如果有任何建议,我将不胜感激,因为我可能很快就会头痛- 您可能需要最后一段。以下awk应起作用:
awk -F/ '{print $(NF-1)}' file
KDBDFC1_5.LIB
FPSENGDEV.LIB
或者,此awk可能通过搜索.LIB和打印第二个字段来工作:
awk -F'.LIB' '{print substr($2,2) FS}' file
KDBDFC1_5.LIB
FPSENGDEV.LIB
您可能需要最后一段。以下awk应起作用:
awk -F/ '{print $(NF-1)}' file
KDBDFC1_5.LIB
FPSENGDEV.LIB
或者,此awk可能通过搜索.LIB和打印第二个字段来工作:
awk -F'.LIB' '{print substr($2,2) FS}' file
KDBDFC1_5.LIB
FPSENGDEV.LIB
怎么样
perl -lne '@matches = /(\w+\.LIB)/g; print $matches[1] if @matches > 1' file
怎么样
perl -lne '@matches = /(\w+\.LIB)/g; print $matches[1] if @matches > 1' file
返回第二次出现的.LIB:
返回上次出现的.LIB:
^从
?:.\.LIB取消捕获包含.LIB的组
.*? 任何不吉利的东西
[\w.]*.LIB第一次捕获组.LIB
任何贪婪的东西
$finish by返回第二次出现的.LIB:
返回上次出现的.LIB:
^从
?:.\.LIB取消捕获包含.LIB的组
.*? 任何不吉利的东西
[\w.]*.LIB第一次捕获组.LIB
任何贪婪的东西
$finish by如果match不支持数组输出,可以运行两次匹配,丢弃第一个匹配,然后打印第二个:
$ awk '{p="[a-zA-Z0-9_]*.LIB"; sub(p,""); match($0,p); print substr($0,RSTART,RLENGTH)}' file
KDBDFC1_5.LIB
FPSENGDEV.LIB
如果match不支持数组输出,则可以运行匹配两次,放弃第一个匹配,然后打印第二个匹配:
$ awk '{p="[a-zA-Z0-9_]*.LIB"; sub(p,""); match($0,p); print substr($0,RSTART,RLENGTH)}' file
KDBDFC1_5.LIB
FPSENGDEV.LIB
所以。。。在搜索正则表达式中添加下划线后,以下内容对我有效:
sed 's/.*\/\([[:alnum:]_]*\.LIB\).*/\1/' file
当然,你也可以用grep-o来代替复杂的正则表达式重写:
grep -o '[[:alnum:]_]*\.LIB' file | awk 'NR%2==0'
它们只使用POSIX兼容的功能,因此在OS/400中应该可以使用。也就是说,您正在awk中查找此项,因此:
awk '{sub(/.*QSYS\.LIB\//,""); sub(/\/.*/,"")}1' file
如果您知道QSYS.LIB是您试图避免的东西,它可能存在于行的前面,那么这可能就可以了。如果它确实是您想要的两个.LIB文件中的第二个文件,则可以执行以下操作:
awk '{match($0,/[[:alnum:]_]+\.LIB/); s=substr($0,RSTART+RLENGTH); match(s,/[[:alnum:]_]+\.LIB/); print substr(s,RSTART,RLENGTH)}' file
或者,为了便于阅读,将其拆分为:
awk '{
match($0,/[[:alnum:]_]+\.LIB/);
s=substr($0,RSTART+RLENGTH);
match(s,/[[:alnum:]_]+\.LIB/);
print substr(s,RSTART,RLENGTH)
}' file
这只使用普通的旧awk函数match和substr,1从中剥离第一个.LIB并将行的剩余部分存储在临时变量中,2在该变量中查找下一个.LIB
它的优点是不依赖于事物的任何特定位置,也就是说,它不假设感兴趣的文件紧跟在第一个文件之后,或者是行中的第二个最后一个文件,等等
这就是说,这很麻烦,阿努巴瓦的第二个解决方案要优雅得多- 所以。。。在搜索正则表达式中添加下划线后,以下内容对我有效:
sed 's/.*\/\([[:alnum:]_]*\.LIB\).*/\1/' file
当然,你也可以用grep-o来代替复杂的正则表达式重写:
grep -o '[[:alnum:]_]*\.LIB' file | awk 'NR%2==0'
它们只使用POSIX兼容的功能,因此在OS/400中应该可以使用。也就是说,您正在awk中查找此项,因此:
awk '{sub(/.*QSYS\.LIB\//,""); sub(/\/.*/,"")}1' file
如果您知道QSYS.LIB是您试图避免的东西,它可能存在于行的前面,那么这可能就可以了。如果它确实是您想要的两个.LIB文件中的第二个文件,则可以执行以下操作:
awk '{match($0,/[[:alnum:]_]+\.LIB/); s=substr($0,RSTART+RLENGTH); match(s,/[[:alnum:]_]+\.LIB/); print substr(s,RSTART,RLENGTH)}' file
或者,为了便于阅读,将其拆分为:
awk '{
match($0,/[[:alnum:]_]+\.LIB/);
s=substr($0,RSTART+RLENGTH);
match(s,/[[:alnum:]_]+\.LIB/);
print substr(s,RSTART,RLENGTH)
}' file
这只使用普通的旧awk函数match和substr,1从中剥离第一个.LIB并将行的剩余部分存储在临时变量中,2在该变量中查找下一个.LIB
它的优点是不依赖于事物的任何特定位置,也就是说,它不假设感兴趣的文件紧跟在第一个文件之后,或者是行中的第二个最后一个文件,等等
这就是说,这很麻烦,阿努巴瓦的第二个解决方案要优雅得多- 你说得对,真的需要最后一节。我没有这样想。我也没有真正想过使用整个子字符串作为字段分隔符。你真的需要最后一个-1段。我没有这样想。我也没有真正想过使用整个子字符串作为字段分隔符。幸运的是,IBM I的最新技术版本包括bash和许多gnu工具,这些工具在aix变体中缺失或无法正常工作。当然,您必须升级旧的AS400-幸运的是,ibmi的最新技术版本包含了bash和许多缺少的gnu工具,或者在aix变体中无法正常工作。当然,您必须升级旧的AS400-