Regex 为什么这个正则表达式匹配只显示capture变量中的第一个单词,而不是整行?

Regex 为什么这个正则表达式匹配只显示capture变量中的第一个单词,而不是整行?,regex,perl,Regex,Perl,我对Perl和正则表达式还比较陌生,所以如果我误用了术语,请耐心等待 我试图读取包含电影脚本的文本文件,并使用正则表达式显示特定角色所说的所有行。以下是我使用的摘录: BRIAN: Hello, mother. MANDY: Don't you 'hello mother' me. What are all those people doing out ther e?! BRIAN: Oh. Well-- well, I, uh-- MANDY: Come on! What have yo

我对Perl和正则表达式还比较陌生,所以如果我误用了术语,请耐心等待

我试图读取包含电影脚本的文本文件,并使用正则表达式显示特定角色所说的所有行。以下是我使用的摘录:

BRIAN: Hello, mother.
MANDY: Don't you 'hello mother' me. What are all those people doing out ther    e?!
BRIAN: Oh. Well-- well, I, uh--
MANDY: Come on! What have you been up to, my lad?!
BRIAN: Well, uh, I think they must have popped by for something.
MANDY: 'Popped by'?! 'Swarmed by', more like! There's a multitude out there!
BRIAN: Mm, they-- they started following me yesterday.
MANDY: Well, they can stop following you right now. Now, stop following my son! You ought to be ashamed of yourselves.
FOLLOWERS: The Messiah! The Messiah! Show us the Messiah!
MANDY: The who?
FOLLOWERS: The Messiah!
MANDY: Huh, there's no Messiah in here. There's a mess, all right, but no Me    ssiah. Now, go away!
FOLLOWERS: The Messiah! The Messiah!
MANDY: Ooooh.
FOLLOWERS: Show us the Messiah! The Messiah! The Messiah! Show us the Messiah!
MANDY: Now, you listen here! He's not the Messiah. He's a very naughty boy! Now, go away!
下面是代码:

  1 use strict;
  2 use warnings;
  3 
  4 my $filename = "movie_script.txt";
  5 my $charname = $ARGV[0];
  6 
  7 if (-e $filename) {
  8     print "File exists.\n";
  9 } else {
 10     print "Alas, file does not exist.\n";
 11     exit 1;
 12 }
 13 
 14 open(my $fh, '<', $filename);
 15 
 16 my $match = "^($charname):.*/i";
 17 
 18 while (my $line = <$fh>) {
 19     if ( $line =~ m/^($charname):.*/i ) {
 20         $line =~ s/($charname): //i;
 21         print $line;                                                
 22     }
 23 }   
 24 print "\n";
 25 close $fh;
。。。而不是布莱恩的四行。所以我尝试交换第22行和第21行,将print$1语句放在regex替换之前,但结果相同

为什么capture变量只显示第一个单词而不是整行?我确信这是一个非常简单的错误,但我很难理解我做错了什么。

$1是您的第一个:匹配正则表达式中第一对括号的部分

如果你有一个带有两组圆括号的正则表达式,那么2美元将与第二部分匹配

以下是脚本中该部分的替代方案:

my $match = qr/^($charname):\s*(.*)/i;

while (my $line = <$fh>) {
    if ( $line =~ m/$match/ ) {
        print "Character : $1\n",
              "text      : $2\n";                                                
    }
}   
为了好玩,这里将是您的完整脚本的一个简短版本,其中包含对正则表达式部分的注释:

#!/usr/bin/env perl

use strict;
use warnings;

my $filename = "/tmp/y";
my $charname = $ARGV[0];

open(my $fh, '<', $filename)
  or die "Cannot find $filename\n";

my $match = qr/^\s* ($charname) \s*:\s* (.*)/ix;
#               |   |              |     |   | \ extended regex which allows spaces for readability
#               |   |              |     |   \ case insensitive
#               |   |              |     \ capture the rest of the line into $2
#               |   |              \ colon, optionally with spaces before and/or after
#               |   \ capture the name into $1
#               \ also accept spaces before the name


while ( <$fh> ) {   # use the default $_ variable instead of unneeded $line
    print "$2\n" if ( /$match/ );
}

print "\n";
close $fh;
$1是第一个:匹配正则表达式中第一对括号的部分

如果你有一个带有两组圆括号的正则表达式,那么2美元将与第二部分匹配

以下是脚本中该部分的替代方案:

my $match = qr/^($charname):\s*(.*)/i;

while (my $line = <$fh>) {
    if ( $line =~ m/$match/ ) {
        print "Character : $1\n",
              "text      : $2\n";                                                
    }
}   
为了好玩,这里将是您的完整脚本的一个简短版本,其中包含对正则表达式部分的注释:

#!/usr/bin/env perl

use strict;
use warnings;

my $filename = "/tmp/y";
my $charname = $ARGV[0];

open(my $fh, '<', $filename)
  or die "Cannot find $filename\n";

my $match = qr/^\s* ($charname) \s*:\s* (.*)/ix;
#               |   |              |     |   | \ extended regex which allows spaces for readability
#               |   |              |     |   \ case insensitive
#               |   |              |     \ capture the rest of the line into $2
#               |   |              \ colon, optionally with spaces before and/or after
#               |   \ capture the name into $1
#               \ also accept spaces before the name


while ( <$fh> ) {   # use the default $_ variable instead of unneeded $line
    print "$2\n" if ( /$match/ );
}

print "\n";
close $fh;

让我们看看您的代码:

while (my $line = <$fh>) {
    if ( $line =~ m/^($charname):.*/i ) {
        $line =~ s/($charname): //i;
        print $line;                                                
    }
} 
您可以在字符串的开头查找字符名,^就是这样做的,后面是冒号,然后是任何其他字符。那是毫无意义的,因为它根本不会改变正则表达式匹配的内容

但是你在$charname周围放的括号做了一些有趣的事情。它们捕获与正则表达式的该部分匹配的字符串位,并将其存储在$1中。老实说,这有点浪费。由于$charname是一个固定字符串,您已经知道$1的最终结果。这将是布赖恩或任何你要找的角色

$line =~ s/($charname): //i;
print $line;
然后编辑$line以删除字符名、冒号和行首的空格。所以你只需要听到对方说的话。你把它打印出来

到目前为止还不错。您的代码在某些地方有点浪费,但它按您的想法执行

然后更改行:

print $line;
致:

你会感到困惑:-

但是正如我们已经看到的,捕获括号将把BRIAN存储在1美元中。所以如果你印1美元,你会看到布赖恩

你问

为什么capture变量只显示第一个单词而不是整行

答案是,因为这就是你要求它做的$1将包含捕获括号内的内容。这是$charname。那是布莱恩。正则表达式匹配的其余部分不在括号内,因此不会以1美元结束


这有意义吗?

让我们看看您的代码:

while (my $line = <$fh>) {
    if ( $line =~ m/^($charname):.*/i ) {
        $line =~ s/($charname): //i;
        print $line;                                                
    }
} 
您可以在字符串的开头查找字符名,^就是这样做的,后面是冒号,然后是任何其他字符。那是毫无意义的,因为它根本不会改变正则表达式匹配的内容

但是你在$charname周围放的括号做了一些有趣的事情。它们捕获与正则表达式的该部分匹配的字符串位,并将其存储在$1中。老实说,这有点浪费。由于$charname是一个固定字符串,您已经知道$1的最终结果。这将是布赖恩或任何你要找的角色

$line =~ s/($charname): //i;
print $line;
然后编辑$line以删除字符名、冒号和行首的空格。所以你只需要听到对方说的话。你把它打印出来

到目前为止还不错。您的代码在某些地方有点浪费,但它按您的想法执行

然后更改行:

print $line;
致:

你会感到困惑:-

但是正如我们已经看到的,捕获括号将把BRIAN存储在1美元中。所以如果你印1美元,你会看到布赖恩

你问

为什么capture变量只显示第一个单词而不是整行

答案是,因为这就是你要求它做的$1将包含捕获括号内的内容。这是$charname。那是布莱恩。正则表达式匹配的其余部分不在括号内,因此不会以1美元结束


这有意义吗?

请研究以下perl脚本如何实现所需的输出

注:

输入存储在_数据块中的测试数据 用于读取文件,请替换为movie_script.pl BRIAN movie_script.txt并作为movie_script.txt运行。 输出示例movie_script.pl FOLLOWERS


请研究以下perl脚本如何实现所需的输出

注:

输入存储在_数据块中的测试数据 用于读取文件,请替换为movie_script.pl BRIAN movie_script.txt并作为movie_script.txt运行。 输出示例movie_script.pl FOLLOWERS


Lou for perl学习书籍在google perl bookshelf中搜索。Lou for perl stu
dy books在google perl书架上搜索。我希望我能接受这三个答案——你花时间耐心地解释捕获变量,这显然是我误解的,而mivk花时间解释正则表达式。谢谢你精彩而深刻的解释!我希望我能接受这三个答案——你花时间耐心地解释捕获变量,这显然是我误解的,而mivk花时间解释正则表达式。谢谢你精彩而深刻的解释!非常感谢,我希望我也能接受这个答案。你对正则表达式的解释非常有用。但是qr/做了什么而m/没有做什么呢?@Lou:qr/用于在变量中定义正则表达式,该变量稍后可以在m/../或/../中使用。使用标准/regex语法时,m是可选的。我在这里使用它是因为您在原始示例中定义了$match变量。啊,我想我明白了。如果我将正则表达式放入没有qr/的标量中,例如,$match=/^$charname:.+$/I,然后在$match的情况下尝试运行print x,我认为这不会起作用?@Lou Yes。if条件不会尝试匹配任何内容,并且总是返回true,因为$match既不是0也不是空的。非常感谢-我希望我也能接受这个答案。你对正则表达式的解释非常有用。但是qr/做了什么而m/没有做什么呢?@Lou:qr/用于在变量中定义正则表达式,该变量稍后可以在m/../或/../中使用。使用标准/regex语法时,m是可选的。我在这里使用它是因为您在原始示例中定义了$match变量。啊,我想我明白了。如果我将正则表达式放入没有qr/的标量中,例如,$match=/^$charname:.+$/I,然后在$match的情况下尝试运行print x,我认为这不会起作用?@Lou Yes。if条件不会尝试匹配任何内容,并且总是返回true,因为$match既不是0也不是空的。
BRIAN
Hello, mother.
Oh. Well-- well, I, uh--
Well, uh, I think they must have popped by for something.
Mm, they-- they started following me yesterday.
FOLLOWERS
The Messiah! The Messiah! Show us the Messiah!
The Messiah!
The Messiah! The Messiah!
Show us the Messiah! The Messiah! The Messiah! Show us the Messiah!