perl 捕获可选连字符regex之间的单词

wlwcrazw  于 2022-11-15  发布在  Perl
关注(0)|答案(4)|浏览(163)

我有以下类型的字符串

abc - xyz
abc - pqr - xyz
abc - - xyz
abc - pqr uvw - xyz

我想从第一个字符串中检索文本xyz,从第二个字符串中检索文本pqr,从第三个字符串和pqr uvw中检索'(空)。第二个连字符是可选的。abc是静态字符串,它必须在那里。我试过下面的正则表达式,

/^(?:abc) - (.*)[^ -]?/

但它会给出以下输出:

xyz
pqr - xyz
- xyz
pqr uvw - xyz

我不需要第二个字符串的最后一部分。我使用Perl编写脚本。可以通过正则表达式完成吗?

gdx19jrr

gdx19jrr1#

请注意,(.*)部分是一个贪婪地量化的点,它尽可能多地获取除换行符字符之外的任何0+字符,直到行尾和[^ -]?,由于?量词,它能够匹配空字符串(*1或0重复 *),匹配行末尾的空字符串。因此,pqr - xyzabc - pqr - xyz输出仅适用于正则表达式引擎。
你需要在这里使用一个更严格的模式。

/^abc\h*-\h*((?:[^\s-]+(?:\h+[^\s-]+)*)?)/

请参阅regex demo

详细数据

  • ^-字符串的开头
  • abc-一个abc
  • \h*-\h*-用0+水平空格括起的连字符
  • ((?:[^\s-]+(?:\h+[^\s-]+)*)?)-组1捕获以下可选事件
  • [^\s-]+-除空格和-之外的1个或多个字符
  • (?:\h+[^\s-]+)*-零次或多次重复
  • \h+- 1+水平空格
  • [^\s-]+- 1个或多个除空格和-以外的字符
ymdaylpp

ymdaylpp2#

您可以使用^[^-]*-\s*\K[^\s-]*
以下是它的工作原理:

^       # Matches at the beginning of the line (in multiline mode)
[^-]*   # Matches every non - characters
-       # Followed by -
\s*     # Matches every spacing characters
\K      # Reset match at current position
[^\s-]* # Matches every non-spacing or - characters

Demo
更新多个括起的单词:^[^-]*-\s*\K[^\s-]*(?:\s*[^\s-]+)*
最后一部分(?:\s*[^\s-]+)*检查是否存在前面有空格的任何其他单词。
Demo

up9lanfz

up9lanfz3#

您可以使用分割:

$answer = (split / \- /, $t)[1];

其中$t是文本字符串,您希望进行第二次拆分(即从0开始的[1])。除abc - - xyz外,其他字符串都有效,但如果分隔符为“-“,则中间应有2个空格,否则不返回任何结果。如果abc - - xyz正确,则您可以在拆分之前执行此操作,以使所有字符串都有效:

$t =~ s/\- \-/-  -/;

它只是插入一个额外的空格,这样它将匹配“-“两次,中间没有任何内容。

webghufk

webghufk4#

可以通过正则表达式完成吗?
是的,有三个简单的正则表达式:一个月一个月一个月一个月一个月一个月一个月一个月

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;

open my $INFILE, '<', 'data.txt';

my @results = map {
    (undef, my $target) = split /-/, $_, 3;
    $target =~ s/^\s+//;  #remove leading spaces
    $target =~ s/\s+$//;  #remove trailing spaces
    $target;
} <$INFILE>;

close $INFILE;

say Dumper \@results;

--output:--
$VAR1 = [
          'xyz',
          'pqr',
          '',
          'pqr uvw'
        ];

相关问题