我有一组包含示例数据的文件,如下所示,我需要转换数据以将所有对象文件(以下)放在-o第一列中,将链接库(以下)-l放在第二列中。这个格式在整个make输出中是一致的。
hello there -o one two three four -labc -lfoo -lbar
something useless -o abc doo zoo -lkoo -lfoo -lmoo
Run Code Online (Sandbox Code Playgroud)
我正在尝试将其解析为更简单的格式以进行进一步处理:
one two three four, abc foo bar
abc doo zoo, koo foo moo
Run Code Online (Sandbox Code Playgroud)
我正在尝试这个,显然这不是我想要得到的:
perl -ne '/-o(.*?)-/m; @libs = /-l([^ ]+)/gs; printf "%s %s\n", $1 , join(", ", @libs);' inputfile
bar
abc, foo, bar
moo
koo, foo, moo
Run Code Online (Sandbox Code Playgroud)
在这里,我尝试将所有对象存储到数组中$1并将所有库存储到@libs数组中。只有库被正确打印,但对象不正确,有人可以帮助修复它吗?我单独验证了它$1是否具有正确的值。
perl -wne '/-o(.*?)-/m; printf "%s %s\n", $1, " "' inputfile
one two three four
abc doo zoo
Run Code Online (Sandbox Code Playgroud)
同样,当我单独打印第二部分(库)时,它也有效。
perl -ne '@libs = /-l([^ ]+)/gs; printf "%s\n", join(", ", @libs);' x
abc, foo, bar
koo, foo, moo
Run Code Online (Sandbox Code Playgroud)
所以,当我将两者结合在一起时,它只会变得混乱。
perl -wnlE'\n ($o, @l) = /-(?:o|l) \\s* ([^-]+) /gx;\n s/\\s+$// for $o, @l; \n say join ", ", $o, "@l"\n' file\nRun Code Online (Sandbox Code Playgroud)\n在file给定的两行上打印
one two three four, abc foo bar\nabc doo zoo, koo foo moo\nRun Code Online (Sandbox Code Playgroud)\n为了使其按预期工作,至关重要的是首先有一个-o选项,然后是后续-l选项(可能有多个),以便以-(o|l)正确的顺序捕获并($o, @l)正确存储。\xe2\x80\xa0
由于可以在 后面列出多个文件-o,并且文件之间有空格,因此我们必须在模式中允许空格,这样也会捕获尾随的文件;因此尾随空格清理是必要的。
(我希望通过调整模式,应该能够纠正这一问题,以便不需要捕获后清理,但我现在看不到它。)
\n\xe2\x80\xa0这个格式已经在评论中确认过了,但是如果有多个-o条目或顺序不同,那么最简单的方法可能是将其分成两个正则表达式
# Capture all `-o` entries, then all `-l` entries (order doesn't matter)\n@o = /-o\\s+([^-]+)/g; @l = /-l\\s*([^-]+)/g; \nRun Code Online (Sandbox Code Playgroud)\n或者,也许对于库来说,宁愿使用
\n@l = /-l(\\S+)/g;\nRun Code Online (Sandbox Code Playgroud)\n然后将它们全部打印为
\nsay join ", ", "@o", "@l";\nRun Code Online (Sandbox Code Playgroud)\n对问题中代码的评论,除了一个障碍之外,实际上是正确的
\n为什么它不起作用:第二个正则表达式填充了自己的捕获变量,因此$1第一个正则表达式被覆盖。解决此问题的一个简单方法是在第一个正则表达式中分配捕获,就像在第二个正则表达式中所做的那样($o) = /-o(.*?)-/(或如此),然后使用它 ( $o)。需要施加列表()上下文$o,以便返回捕获,而不仅仅是成功/失败(1/'' )
其他一些注意事项
\n不需要/m也不需要/s,那些用于多行字符串
[^ ]可以写成\\S(非空格:),我认为这样更清晰。所以/-l(\\S+)/g
printf当我们需要格式化打印时,它非常强大和有用。在这里你不这样做,所以没有理由这样做,虽然它慢得多并且容易出错;可以做print join(...), "\\n";。
或者使用say,enabled by-E来代替-e。由于-E启用了所有其他功能,并且可能无法面向未来,因此最好CORE::say与 一起使用-e。在你会做的程序中use feature 'say';在你一开始