【问题标题】:Multiple occurence of string in a line to be grepped一行中多次出现字符串被 grep
【发布时间】:2014-06-23 09:50:18
【问题描述】:

我有两个问题。

1:如果我有这样一行“Fruits: Mango Banana”,我想捕获“Mango Banana”部分并将其分配给另一个变量。目前我正在关注这个,

if(/$line == Fruits:\s(\w+)/){
myFav=$1;
}

但它只返回“芒果”而不是“芒果香蕉”。任何人都可以建议如何获得由空格分隔的完整水果列表。

2:如果我在同一行中重复了一些字符串,我想捕获所有出现的情况。

例如:如果我有类似“我有水果:芒果,水果的颜色:香蕉是绿色”这样的行。我也想同时捕获 Mango 和 Banana 值。

if(/$line == Fruit:\s(\w+)/){
myFav=$1;
}

通常,上述代码在“Fruit:”第一次出现后停止搜索。任何人都可以帮助解决上述两个问题吗?

提前致谢:)

【问题讨论】:

  • 两个问题最好用两个帖子来解决。

标签: perl


【解决方案1】:

一种解决方案是依靠您的水果名称大写这一事实。

但是,我倾向于使用两个正则表达式,一个用于 Fruits,一个用于 Fruit。

use strict;
use warnings;

while (<DATA>) {
    chomp;
    while (/Fruits?: ((?:[A-Z]\w*\s*)+)(?<!\s)/g) {
        print "Line $. - '$1'\n";
    }
}

__DATA__
Fruits: Mango Banana
I have Fruit: Mango and the color of the Fruit: Banana is green

输出:

Line 1 - 'Mango Banana'
Line 2 - 'Mango'
Line 2 - 'Banana'

【讨论】:

    【解决方案2】:

    改用这个:([\w\s]+)

    if($line =~ /Fruits:\s([\w\s]+)/) {
        $myFav = $1;
    }
    

    总是这样:

    use strict;
    use warnings;
    

    【讨论】:

      【解决方案3】:
      $line="I have Fruit: Mango and the color of the Fruit: Banana is green";
      @found=($line=~m/Fruit: \w+/g); # Make sure to use g operator, finds all matches in $line
      for each $s (@found)
          {print "$s\n";
          }
      

      【讨论】:

        【解决方案4】:

        1/ 正则表达式只返回“Mango”的原因是 \w+ 匹配“word”字符。即数字、字母和下划线(即在 Perl 符号名称中有效的字符)。如果你想匹配两个水果名称之间的空格,那么你需要在你的正则表达式中添加一个空格(或者,也许更好,\s 匹配所有空格)。您可能希望将这两个原子都放在一个字符类中。

        /Fruit:\s([\w\s]+)/
        

        2/ 默认情况下,匹配运算符仅匹配输入字符串中第一次出现的正则表达式。为了匹配所有这些,您需要将/g 选项添加到匹配运算符。

        /Fruit:\s([\w\s]+)/g
        

        其他一些您可能会觉得有用的注释:

        • Perl regex tutorial 是学习这些东西的好方法
        • Perl regex documentation 包含所有血腥细节。
        • Perl operator documentation 解释了匹配运算符。
        • 在所有代码中添加use strictuse warnings 是一个很好的习惯。
        • 您使用绑定运算符 (=~) 而不是赋值运算符 (=) 再次将字符串匹配为正则表达式。并且输入字符串和绑定操作符在匹配操作符之外。

          if($line =~ /Fruits:\s(\w+)/){

        【讨论】:

          【解决方案5】:

          在您的第一篇文章中,您使用的是:

          if ( /$line == Fruits:\s(\w+)/ ) {
          

          首先,对于正则表达式,您应该使用~= 而不是==。其次,您可以像这样在正则表达式周围加上斜线:

          if ( $line ~= /Fruits:\s(\w+)/ ) {
          

          现在,\w+ 代表一个单词,其中包括字母、数字、下划线,仅此而已。它不匹配空格。

          你有:

          Fruits: Mango Banana
          

          所以,\w+ 将匹配 Mango,但将停止匹配 Mango 之后的空格。

          如果你想同时匹配:

          if ( $line =~ /^Fruits:\s+(.+)/ ) {
          

          注意. 将匹配任何字符,包括空格。插入符号表示至少匹配一个空格。星号匹配零个或多个。注意我也使用\s+ 而不仅仅是\s。这样,如果Fruits 后面有多个空格,就会匹配到。

          在您的第二个示例中,您可以这样做:

          my @fruits = $line =~ /Fruits:\s+(\S+)/g
          

          末尾的g 允许多个匹配项。否则,只会使用第一个。 \S 代表所有非空白空间,其中包括可能的破折号。这会将您的匹配项放入数组@fruits。阅读Regular Expression Tutorial。它将帮助您更好地了解正在发生的事情。

          在您的程序中始终使用use strict;use warnings;。它将帮助您捕获错误。您必须使用my 声明变量,但这是值得的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多