我的输入字符串如下所示:
1 warning: rg: W, MULT: file 'filename_a.h' was listed twice.
2 warning: rg: W, SCOP: scope redefined in '/proj/test/site_a/filename_b.c'.
3 warning: rg: W, ATTC: file /proj/test/site_b/filename_c.v is not resolved.
4 warning: rg: W, MULTH: property file filename_d.vu was listed outside.
它们有四种不同的味道,如上所列。我逐行从日志文件中读取这些内容。
对于指定路径的那个(第2,3行),我可以使用$file=~s#.*/##;
提取文件名,似乎工作正常。有没有办法不使用不同类型的条件语句并提取文件名?我想只使用一个干净的正则表达式并提取文件名。在这种情况下,Perl的File::basename
也不起作用。
我正在使用Perl。
答案 0 :(得分:2)
您的问题需要更多限制。例如,将字符串表征为“路径”(或“文件名”)的好方法是什么?你可能会说,“嘿,当我看到一个点后面紧跟着字母和数字(但不是符号),并且在该点之前还有一堆字符,那么它可能是一个路径或文件名!”
\s+([^\s]+\.\w+)
但这并没有捕获所有路径,也没有没有扩展名的文件。所以我们可能会在交替上说“上面的,或者是一个至少有一个斜线的字符串。”
\s+([^\s]+\.\w+|[^\s]*\/[^\s]*)
(请注意,您可能不需要在上面的示例中转义斜杠,因为您似乎使用#
作为分隔符。)
无论如何,我得到的是,您需要更严格地指定问题,这将自动为您带来满意的解决方案。当然,没有单独使用正则表达式的真正“正确”解决方案:您需要进行文件测试才能做到这一点。
要进一步了解此示例,您可能希望定义扩展列表:
\s+([^\s]+\.(?:c|h|cc|cpp)|[^\s]*\/[^\s]*)
或许,您可能想要更通用,但只允许最多4个字符的扩展名:
\s+([^\s]+\.\w{1,4}|[^\s]*\/[^\s]*)
也许你只考虑一个路径,如果它以斜杠开头,但你仍然希望其中至少有另一个斜杠:
\s+([^\s]+\.\w{1,4}|/[^\s]*\/[^\s]*)
祝你好运。
答案 1 :(得分:2)
你可以分两步完成:
#!/usr/bin/perl -n
use feature 'say';
use File::Basename;
#NOTE: assume that unquoted path has no spaces in it
say basename($1.$2) if /(?:file|redefined in)\s+(?:'([^']+)'|(\S+))/;
filename_a.h
filename_b.c
filename_c.v
filename_d.vu
答案 2 :(得分:0)
/ \ W *。\ W * / 这将匹配四个不同警告日志中表示的文件名。 \ w将匹配任何单词字符(字母,数字和下划线),因此此正则表达式查找任意数量的单词字符,后跟一个点后跟更多单词字符。 这是有效的,因为日志中唯一的其他点位于日志的末尾。