Regex 捕获可选连字符正则表达式之间的单词

Regex 捕获可选连字符正则表达式之间的单词,regex,perl,hyphen,Regex,Perl,Hyphen,我有以下类型的字符串 abc - xyz abc - pqr - xyz abc - - xyz abc - pqr uvw - xyz 我想从第一个字符串中检索文本xyz,从第二个字符串中检索文本pqr,从第三个字符串中检索文本“`”(空)&pqr uvw。第二个连字符是可选的abc是静态字符串,它必须存在。我试着跟着regex /^(?:abc) - (.*)[^ -]?/ 但它给了我以下输出 xyz pqr - xyz - xyz pqr uvw - xyz 我不需要第二个字符串的最

我有以下类型的字符串

abc - xyz
abc - pqr - xyz
abc - - xyz
abc - pqr uvw - xyz
我想从第一个字符串中检索文本
xyz
,从第二个字符串中检索文本
pqr
,从第三个字符串中检索文本“`”(空)&
pqr uvw
。第二个连字符是可选的<代码>abc是静态字符串,它必须存在。我试着跟着regex

/^(?:abc) - (.*)[^ -]?/
但它给了我以下输出

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

注意,
(.*)
部分是一个贪婪量化的点,它尽可能多地抓取除换行符以外的任何0+字符,直到行尾和
[^-]?
,由于
量词(1或0次重复),能够匹配空字符串,匹配行末尾的空字符串。因此,
abc-pqr-xyz
pqr-xyz
输出仅适用于正则表达式引擎

这里需要使用更严格的模式。例如

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

详细信息

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

您可以使用
^[^-]*-\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


多个封闭单词的更新:
^[^-]*-\s*\K[^\s-]*(?:\s*[^\s-]+)*

最后一部分
(?:\s*[^\s-]+)*
检查是否存在前面有空格的任何其他单词

可以通过regex完成吗

是的,有三个简单的正则表达式:
-
^\s+
\s+$

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'
        ];
使用严格;
使用警告;
使用5.020;
使用自动模具;
使用数据::转储程序;
打开我的$infle,“您可以使用拆分:

$answer = (split / \- /, $t)[1];
其中,$t是文本字符串,您需要第二次拆分(即,[1]从0开始)。除了ABX-XYZ以外的所有工作,但是如果分隔符是“--”,那么中间应该有2个空格来返回任何东西。如果abc--xyz是正确的,则可以在拆分之前执行此操作,以便所有人都能正常工作:

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

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

Try@S.Kablar请尽量不要在评论中回答,更多的是使用外部链接。一个恰当的答案,为什么不加解释,会好得多……太完美了!它起作用了@如果您能添加答案和一些解释,我可以将其标记为答案。
abc
是动态的还是静态的?如果它是静态的,只需使用
/^abc\h*-\h*(\S+)/
怎么办?@Abhishek和怎么办?它可以工作,但它也考虑了
\n
。我只需要照顾空间,但不是新线。@Abhishek,现在不应该了。并且它仍然可以在组1中返回空值。是。。非常感谢。相应地编辑了我的答案。谢谢。。但更新后的版本也考虑了\n。我只需要注意空格,而不是新行。你有没有按照@wiktor的建议尝试使用水平空格?