Extract certain part of a string in Perl
我有以下Perl字符串。长度和图案不同。该文件始终命名为*log.999
1 2 3 4
| my $file1 = '/user/mike/desktop/sys/syslog.1';
my $file2 = '/user/mike/desktop/movie/dnslog.2';
my $file3 = '/haselog.3';
my $file4 = '/user/mike/desktop/movie/dns-sys.log' |
我需要提取log之前的单词。在这种情况下,sys,dns,hase和dns-sys。
如何编写正则表达式来提取它们?
- 您说"名为XXXXlog.num的文件",但是您的示例显示了一个目录.../syslog.1/'(请注意末尾的斜杠)-是哪个?而且,这始终是名称/路径中的最后一件事吗?
-
@zdim对此感到抱歉。我的意思是文件名(XXXXlog.num)始终是整个路径中的最后一件事。
匹配一个或多个字母数字字符,后跟log(但不匹配logging等)。
如果文件名格式是固定的,则可以使用
使正则表达式更可靠
显示的字符串的主要属性是*log*短语是最后一个。
然后锚定模式,因此我们不会在中间的某个位置匹配log
1
| my ($name) = $string =~ /(\\w+)log\\.[0-9]+$/; |
而如果.N扩展名是可选的
1
| my ($name) = $string =~ /(\\w+)log(?:\\.[0-9]+)?$/; |
上面使用\\w+模式捕获log之前的文本。但是该文本也可能包含非单词字符(-,.等),在这种情况下,我们将使用[^/]+捕获最后一个/之后的所有内容,如阿比盖尔的回答所指出的那样。对于注释中的每个问题,使用.N可选
1
| my ($name) = $string =~ m{ ([^/]+) log (?: \\ .[0-9]+ )? $ }x ; |
我在其中添加了}x修饰符的地方,其中的空格将被忽略,这有助于提高可读性。
我使用了一组除/以外的定界符,以便能够在内部使用/而不会对其进行转义,然后m是强制性的。 [^...]是否定的字符类,与未在其中列出的任何字符匹配。因此[^/]+log匹配log之前的所有不是/的连续字符。
非捕获组(?: ... )对内部的模式进行分组,因此?适用于整个组,但不必要捕获它们。
(?:\\.[0-9]+)?模式是专门为禁止诸如log.(在点号之后)和log5之类的东西而编写的。但是,如果可以接受,则将其更改为更简单的\\.?[0-9]*
更新纠正了代码中的错字:对于可选的.N,存在+,而不是*
-
只是一个小问题。为什么我们需要在($ name)上加上括号而不是使用$ name呢? @zdim
-
@Luke匹配运算符(m/.../)返回的内容取决于上下文。在标量上下文中(在if ($v =~ /.../)或$ret = $v =~ /.../(例如)中),它返回true / false。在列表上下文中,它返回实际的匹配列表。因此,我们需要在其上加上列表上下文,这是parens ($match) = $v =~ /.../所做的。或者我们当然可以说@matches = $v =~ /.../。
-
所以在这种情况下,它返回true / false对吗?我认为我的$ filepath是标量上下文。.因此,为了在其上转换true / false,那么我们需要使用parens()吗?我不太明白。非常感谢@zdim
-
@Luke此上下文事务与正则表达式匹配有关。使用括号,它将返回实际匹配项(不只是true / false),因此我们得到sys或类似的结果。 (如果没有括号,它将返回1或空字符串,表示为false!)。您在问题中显示的文件名只是一个普通的赋值,即将字符串分配给变量。那里不需要括号。
-
哦。 GOTCHA。欣赏它。
-
如果我有像Abigail所说的带有破折号的字符串怎么办,如何根据您的.N可选大小写来修复正则表达式。假设my $file2 = '/user/mike/desktop/movie/dns-sys.log';如何提取dns-sys?
-
@Luke更新了答案
-
@Luke我添加了更多内容,并修复了可选部分中的错字。 (它具有*,而它应该具有+,如所描述的那样工作。)谢谢您让我再看一次。
-
感谢您一直以来的清晰解释,这非常有帮助。我从您那里学到了很多有关Regex的知识。 @zdim