捕获可选连字符正则表达式之间的单词
Capture word between optional hyphens regex
我有以下类型的字符串,
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 编写脚本。可以通过正则表达式完成吗?
请注意,(.*)
部分是一个贪婪量化的点,它会抓取除换行符以外的任何 0+ 个字符,尽可能多,直到行尾和 [^ -]?
, 由于 ?
量词(1 或 0 次重复),能够匹配空字符串,匹配行尾的空字符串。因此,abc - pqr - xyz
的 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 个或更多字符
你可以使用 ^[^-]*-\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-]+)*
检查是否存在以 space(s) 开头的任何其他单词。
Can it be done via 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'
];
你可以使用拆分:
$answer = (split / \- /, $t)[1];
其中 $t 是文本字符串,您想要第二次拆分(即 [1] 从 0 开始)。适用于除 abc - - xyz 之外的所有内容,但如果分隔符是“-”,则中间应该有 2 spaces 到 return 什么都没有。如果 abc - - xyz 是正确的,那么您可以在拆分之前执行此操作以使所有工作正常:
$t =~ s/\- \-/- -/;
它只是插入一个额外的 space,所以它会匹配“-”两次,中间没有任何内容。
我有以下类型的字符串,
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 编写脚本。可以通过正则表达式完成吗?
请注意,(.*)
部分是一个贪婪量化的点,它会抓取除换行符以外的任何 0+ 个字符,尽可能多,直到行尾和 [^ -]?
, 由于 ?
量词(1 或 0 次重复),能够匹配空字符串,匹配行尾的空字符串。因此,abc - pqr - xyz
的 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 个或更多字符
你可以使用 ^[^-]*-\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-]+)*
检查是否存在以 space(s) 开头的任何其他单词。
Can it be done via 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'
];
你可以使用拆分:
$answer = (split / \- /, $t)[1];
其中 $t 是文本字符串,您想要第二次拆分(即 [1] 从 0 开始)。适用于除 abc - - xyz 之外的所有内容,但如果分隔符是“-”,则中间应该有 2 spaces 到 return 什么都没有。如果 abc - - xyz 是正确的,那么您可以在拆分之前执行此操作以使所有工作正常:
$t =~ s/\- \-/- -/;
它只是插入一个额外的 space,所以它会匹配“-”两次,中间没有任何内容。