Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl REGEXP如何从没有备用模式的单词中匹配子字符串?_Regex_Perl - Fatal编程技术网

Perl REGEXP如何从没有备用模式的单词中匹配子字符串?

Perl REGEXP如何从没有备用模式的单词中匹配子字符串?,regex,perl,Regex,Perl,大家下午好 我有一串空格分隔的单词。我需要从字符串中找到与字母数字模式匹配的单词,部分或整个单词。 我需要只由字母数字字符组成的单词 为了使我的目的更清楚,我有以下条件: “foo bar quux foo foo bar foo quux barfoo Barbor Barqux”。 “quuxfoo quuxbar Quuxqux[foo]foo{foo}foo barfoo”。 “quuxfoo foo 2foo 2bar foo 2Quux foo 2foo bar2foo quux2f

大家下午好

我有一串空格分隔的单词。我需要从字符串中找到与字母数字模式匹配的单词,部分或整个单词。 我需要只由字母数字字符组成的单词

为了使我的目的更清楚,我有以下条件:

“foo bar quux foo foo bar foo quux barfoo Barbor Barqux”。 “quuxfoo quuxbar Quuxqux[foo]foo{foo}foo barfoo”。 “quuxfoo foo 2foo 2bar foo 2Quux foo 2foo bar2foo quux2foo 2foo 2foo”

我想找到所有的单词,每个单词里面只有一次'foo',而不是那些带有特殊字符的单词,比如[foo],{foo}

我用Perl中的以下代码完成了这项工作:

my $s=
'foo bar quux foofoo foobar fooquux barfoo barbar barquux quuxfoo quuxbar quuxquux ' .
'[foo] (foo) {foo} foofoo barfoo quuxfoo foo2foo foo2bar foo2quux foo2foo bar2foo quux2foo';
my @m = ($s=~/(\w+foo|foo\w+|^foo|foo$)/g) ;
say "@m";
say "Number of sub-strings matching the pattern: ", scalar @m;
print( sprintf("%02d: ",$_),
       ($s=~/(\w+foo|foo\w+|^foo|foo$)/g)[$_],
       qq(\n) )
    for (0..@m-1);
我得到了我想要的结果:

foo foofoo foobar fooquux barfoo quuxfoo foofoo barfoo quuxfoo foo2foo foo2bar foo2quux foo2foo bar2foo quux2foo
Number of sub-strings matching the pattern: 15 
00: foo
01: foofoo
02: foobar
03: fooquux
04: barfoo
05: quuxfoo
06: foofoo
07: barfoo
08: quuxfoo
09: foo2foo
10: foo2bar
11: foo2quux
12: foo2foo
13: bar2foo
14: quux2foo
但是,如果我需要并且愿意在更复杂的字符串中添加更多的模式来搜索,它很快就会变得混乱,我会对交替模式“|”的连续性感到困惑

是否有人帮助我编写一个更短/更清晰的模式regexp,以一种可以用一种模式编写的方式来分隔“foo”或任何其他单词/子单词

先谢谢你

通用汽车

W7/64上的草莓5.022,但我认为它对于5.016甚至5.008以上的任何Perl都是相当通用的

我发现道格和斯特芬的解决方案太适合我了。grep不是最具可读性的,它更符合我的Perl水平,但我认为,作为基于纯regexp的,它更能够处理未来的单词添加,并且具有单词限制 处理

我想在这里写下我对它的理解,以便在我打算根据我的实际需要扩展它之前,如果我错了,你可以纠正我

(?:         # You start a non capturing group.
(?<=        # You start a lookbehind (so non capturing BY NATURE, am I right ?, because
            # if not, as it is being enclosed in round-brackets '()' it restarts to be
            # capturing even inside a non capturing group, isn't it?)
 \h         # In the lookbehind you look for an horizontal space (could \s have been used
            # there?)
 ^          # in the non capturing group but outside of the lookbehind you look for the
            # start of string anchor. Must not be present in the lookbehind group because
            # it requires a same length pattern size and ^ has length==0 while \h is
            # non zero.
\w*foo\w*   # You look for foo within an alphanum word. No pb to have '*' rather than '+'
            # because your left (and right, that we'll see it down) bound has been well
            # restricted.
(?=         # You start a lookforward pattern (non capturing by nature here again, right?),
            # to look for:
\h or $     # horiz space or end of string anchor. However the lookaround size is
            # different here as $ is still 0 length (as ^ anchor) and \h still non
            # zero. "AND YET IT MOVES" (I tested your regexp and it worked) because
            # only the lookbehind has the 'same-size' pattern restriction, right?
谢谢你们的帮助,各位,在最后一点之后,我不再用我的小问题来烦你们了,并考虑我的问题得到了完全的回答。
G.

可能先过滤不需要的单词,然后对过滤后的单词使用grep:

use strict;
use warnings;

my $s=
'foo bar quux foofoo foobar fooquux barfoo barbar barquux quuxfoo quuxbar quuxquux ' .
'[foo] (foo) {foo} foofoo barfoo quuxfoo foo2foo foo2bar foo2quux foo2foo bar2foo quux2foo';

my @words = ( $s=~/(?:(?<=\h)|^)(\w+)(?=\h|$)/g );

my @foos = grep(/foo/, @words);

while (my ($i, $v) = each @foos) {
    printf "%02d: %s\n", $i,$v;
}
或者,您可以组合对按水平空格分割的单词列表进行过滤,并测试生成的单词是否全部为字母数字:

@foos=grep {/foo/ && /^\w+$/} split /\h/, $s;  # same result
或者

或者,在以下情况下:

根据评论中的要求,包括:

$s=~/(?:(?<=\h)|^)(\w*foo\w*)(?=\h|$)/g


(?:(?<=\h)|^)  Assert either after a \h (horizontal space) or at start of line ^
(\w*foo\w*)    Capture a 'word' with 'foo' and only \w characters (or, [a-zA-Z0-9_] characters)
(?=\h|$)       Assert before either a \h horizontal space or end of line $

唯一棘手的部分是?:?可能先过滤不需要的单词,然后对过滤后的单词使用grep:

use strict;
use warnings;

my $s=
'foo bar quux foofoo foobar fooquux barfoo barbar barquux quuxfoo quuxbar quuxquux ' .
'[foo] (foo) {foo} foofoo barfoo quuxfoo foo2foo foo2bar foo2quux foo2foo bar2foo quux2foo';

my @words = ( $s=~/(?:(?<=\h)|^)(\w+)(?=\h|$)/g );

my @foos = grep(/foo/, @words);

while (my ($i, $v) = each @foos) {
    printf "%02d: %s\n", $i,$v;
}
或者,您可以组合对按水平空格分割的单词列表进行过滤,并测试生成的单词是否全部为字母数字:

@foos=grep {/foo/ && /^\w+$/} split /\h/, $s;  # same result
或者

或者,在以下情况下:

根据评论中的要求,包括:

$s=~/(?:(?<=\h)|^)(\w*foo\w*)(?=\h|$)/g


(?:(?<=\h)|^)  Assert either after a \h (horizontal space) or at start of line ^
(\w*foo\w*)    Capture a 'word' with 'foo' and only \w characters (or, [a-zA-Z0-9_] characters)
(?=\h|$)       Assert before either a \h horizontal space or end of line $

唯一棘手的部分是?:?这取决于:如果你想从foobar获得foobar,那很容易。您只需将foo与前后可选的单词字符进行匹配,然后在两侧匹配一个单词边界\b,该边界可以是输入的开头或一些非单词字符:

my @m = ($s=~/(\b\w*foo\w*\b)/g);
print( sprintf("%02d: ",$_),
    ($s=~/(\b\w*foo\w*\b)/g)[$_],
    qq(\n) )
for (0..@m-1);
输出:

00: foo
01: foofoo
02: foobar
03: fooquux
04: barfoo
05: quuxfoo
06: foo
07: foo
08: foo
09: foofoo
10: barfoo
11: quuxfoo
12: foo2foo
13: foo2bar
14: foo2quux
15: foo2foo
16: bar2foo
17: quux2foo
如果没有,那就有点难了。在这里,我将匹配输入的开头或空格,然后用可选的单词字符包围foo,然后我们需要一个零长度断言,它需要一个空格或输入的结尾:

my @m = ($s=~/(?:^|\s)(\w*foo\w*)(?=\s|$)/g);
print( sprintf("%02d: ",$_),
    ($s=~/(?:^|\s)(\w*foo\w*)(?=\s|$)/g)[$_],
    qq(\n) )
for (0..@m-1);
输出:

00: foo
01: foofoo
02: foobar
03: fooquux
04: barfoo
05: quuxfoo
06: foofoo
07: barfoo
08: quuxfoo
09: foo2foo
10: foo2bar
11: foo2quux
12: foo2foo
13: bar2foo
14: quux2foo

这取决于:如果你想从foobar那里得到foobar,那很容易。您只需将foo与前后可选的单词字符进行匹配,然后在两侧匹配一个单词边界\b,该边界可以是输入的开头或一些非单词字符:

my @m = ($s=~/(\b\w*foo\w*\b)/g);
print( sprintf("%02d: ",$_),
    ($s=~/(\b\w*foo\w*\b)/g)[$_],
    qq(\n) )
for (0..@m-1);
输出:

00: foo
01: foofoo
02: foobar
03: fooquux
04: barfoo
05: quuxfoo
06: foo
07: foo
08: foo
09: foofoo
10: barfoo
11: quuxfoo
12: foo2foo
13: foo2bar
14: foo2quux
15: foo2foo
16: bar2foo
17: quux2foo
如果没有,那就有点难了。在这里,我将匹配输入的开头或空格,然后用可选的单词字符包围foo,然后我们需要一个零长度断言,它需要一个空格或输入的结尾:

my @m = ($s=~/(?:^|\s)(\w*foo\w*)(?=\s|$)/g);
print( sprintf("%02d: ",$_),
    ($s=~/(?:^|\s)(\w*foo\w*)(?=\s|$)/g)[$_],
    qq(\n) )
for (0..@m-1);
输出:

00: foo
01: foofoo
02: foobar
03: fooquux
04: barfoo
05: quuxfoo
06: foofoo
07: barfoo
08: quuxfoo
09: foo2foo
10: foo2bar
11: foo2quux
12: foo2foo
13: bar2foo
14: quux2foo

您可以拆分字符串并筛选数组:

use strict;
use warnings;

my $s=
'foo bar quux foofoo foobar fooquux barfoo barbar barquux quuxfoo quuxbar quuxquux ' .
'[foo] (foo) {foo} foofoo barfoo quuxfoo foo2foo foo2bar foo2quux foo2foo bar2foo quux2foo';

my @res = grep {/foo/ && !/\W/}  split /\s/, $s;

print join(" ", @res);

您可以拆分字符串并筛选数组:

use strict;
use warnings;

my $s=
'foo bar quux foofoo foobar fooquux barfoo barbar barquux quuxfoo quuxbar quuxquux ' .
'[foo] (foo) {foo} foofoo barfoo quuxfoo foo2foo foo2bar foo2quux foo2foo bar2foo quux2foo';

my @res = grep {/foo/ && !/\W/}  split /\s/, $s;

print join(" ", @res);

你是想从foobar那里得到foobar,还是根本不应该得到那场比赛?@steffen:不,你是对的,我不想有foo或[foo]或{foo}或;傅;,等等,嘿,把第二部分移到一个新的答案,接受它;你是想从foobar那里得到foobar,还是根本不应该得到那场比赛?@steffen:不,你是对的,我不想有foo或[foo]或{foo}或;傅;,等等,嘿,把第二部分移到一个新的答案,接受它;为了排除单词前面或后面的so parens作为单词边界,我发现在变量中的第一个示例中使用qr更清楚地创建您自己的单词边界[^…]为了排除单词前面或后面的so parens作为单词边界,我发现更清楚地创建您自己的单词边界[^…]在第一个例子中,在一个带有qr的变量中,这是正确的方向。保持简单。请记住,正则表达式使用的“单词字符”的定义是字母、数字和下划线,因此,如果您有更具体的要求,您可能需要构造一个新的字符。很好!谢谢我不是第一眼就明白的。现在我想我更明白了。我不会在regexps中使用它取得进展,但它会立即解决我的pb问题。我在快速解决和学习之间保持平衡。我会尽量做到两个。真的,正如佩尔大师所说,有不止一种方法可以做到这一点。这是正确的方向。保持简单。记住
正则表达式使用的“单词字符”的定义是字母、数字和下划线,因此如果您有更具体的要求,您可能需要构造一个!谢谢我不是第一眼就明白的。现在我想我更明白了。我不会在regexps中使用它取得进展,但它会立即解决我的pb问题。我在快速解决和学习之间保持平衡。我会尽量做到两个。真的,正如佩尔大师所说,有不止一种方法可以做到这一点。谢谢@foos=$s=~/?:?@GillesMaisonneuve:添加了解释。谢谢@foos=$s=~/?:?@GillesMaisonneuve:添加了解释。