【问题标题】:Perl string manipulation and findPerl 字符串操作和查找
【发布时间】:2018-10-18 00:31:40
【问题描述】:

我目前正在为一个班级编写电话簿程序,我在正则表达式部分遇到了一些麻烦,以便格式化我的文本并找到我正在寻找的内容。首先,我无法将我的电话号码文本编辑成我想要的内容。我能够找到连续有 7 个数字的文本 (777777),但我无法将其替换为 (1-701-777-777)。

if($splitIndex[1] =~ m/^(\d{3}\d{4})/) {
      $splitIndex[1] =~ s/([\d{3}][\d{4}])/1-701-[$1]-[$2]/;
      print "Updated: $splitIndex[1]";
    }

当我运行这段代码时,输​​出最终是(我不能在这里嵌入图像是输出https://imgur.com/a/8HtW7xm)。

其次,我在执行搜索的实际正则表达式部分时遇到了麻烦。我将所有可能的字母组合保存在 $letofSearch 中,将数字顺序组合保存在 $numOfSearch 中。通过在正则表达式中玩耍,我知道如果我做 [$numOfSearch]+[$numOfSearch[-1]...[$numOfSearch[1] 它给了我正确的数字查找,但我无法正确地写它在我的代码中。

    #If user input is only numbers
    if($searchValue =~ m/(\D)/) {
      #print "Not a number\n";
      if($splitIndex[1] =~ m/([$numOfSearch]+)/) {
        if($found == 0) {
            print "$splitIndex[0]:$splitIndex[1]\n";
            $found = 1;
        }
      }
      if($splitIndex[0] =~ m/([$letOfSearch])/i) {
        if($found == 0) {
            print "$splitIndex[0]:$splitIndex[1]\n";
            $found = 1;
        }
      }
      $found = 0;
    } else {
      #If it is a number search for that number combo immedietly
      if($splitIndex[1] =~ m/([$numOfSearch]+)/) {
        if($found == 0) {
            print "$splitIndex[0]:$splitIndex[1]\n";
            $found = 1;
        }
      }
      if($splitIndex[0] =~ m/([$letOfSearch])/i) {
        if($found == 0) {
            print "$splitIndex[0]:$splitIndex[1]\n";
            $found = 1;
        }
      }
      $found = 0;
    }
  }
}

【问题讨论】:

  • 嗯。你认为()[] 在正则表达式中做了什么?

标签: regex string perl search substitution


【解决方案1】:

代替:

if($splitIndex[1] =~ m/^(\d{3}\d{4})/) {
      $splitIndex[1] =~ s/([\d{3}][\d{4}])/1-701-[$1]-[$2]/;
      print "Updated: $splitIndex[1]";
    }

试试这个:

if ($splitIndex[1] =~ s/(\d{3})(\d{4})/1-701-$1-$2/)
{
    print "Updated: $splitIndex[1]";
}

在正则表达式中,一组方括号([])将匹配一个且只有一个 字符,无论括号之间是什么。因此,当您编写[\d{3}][\d{4}] 时,它将匹配正好两个字符,因为您使用的是两个[]。这两个字符将是\d(任何数字)、{34} 之一,因为这是您在括号内写的。

正则表达式的方括号内的顺序无关紧要,因此[\d{3}][}1527349806{3] 相同。如您所见,这可能不是您想要的。

您的本意是capture \d{3}\d{4} 字符串,然后使用一组常规的capturing 括号来实现,如下所示:@ 987654336@

由于您只有一组括号(即,您有([\d{3}][\d{4}]))并且它正好包含两个[]s,因此它正好将两个字符放入$1,而没有放入$2。这就是为什么当您尝试在 s/// 的后半部分使用 $2 时,它抱怨 $2 中的值未初始化。您试图使用一个根本没有设置的值 ($2)。

(另外,您正在进行两组匹配:一组用于m//,一组用于s///。我只是删除了m// 匹配并保留s/// 匹配,使用它的返回值确定我们是否需要 print() 任何东西。)

s/// 的第二部分不使用正则表达式,因此任何 []{}() 都将显示为该字符.因此,如果您不想在最终电话号码中使用方括号,请不要使用它们。这就是我使用s/.../1-701-$1-$2/; 而不是s/.../1-701-[$1]-[$2]/; 的原因。

所以当您编写s/([\d{3}][\d{4}])/1-701-[$1]-[$2]/ 时,([\d{3}][\d{4}]) 部分是将两个字符放入 $1,而没有放入 $2。这就是为什么您得到的结果包含 [77](用括号括起来的 $1)和 [](用括号括起来的 $2(未初始化的值))。

至于您帖子的第二部分,我注意到您在正则表达式中使用了很多捕获括号,但您从未真正使用您捕获的内容。也就是说,您永远不会使用 $1(或 $2)。例如,你写:

if($searchValue =~ m/(\D)/) {

其中有 m/(\D)/,但您从不在该代码的任何地方使用 $1。我想知道:如果您不在代码中的任何地方使用该非数字字符,那么捕获它有什么意义?

我看到程序员混淆了括号和方括号的用途。使用正则表达式时,方括号([]匹配(不捕获)正好一个字符。它们匹配的是放入 $1、$2 或任何其他 $n。

另一方面,括号捕获匹配的任何内容,通过将 $1(或 $2、$3 等)设置为匹配的内容。通常,除非您打算稍后捕获并使用该匹配项,否则不应使用括号。 (此规则的主要例外是如果您需要对一组匹配项进行分组,例如:m/I have a (cat|dog|bird)/。)

许多程序员混淆了正则表达式中的方括号和圆括号,并尝试互换使用它们。他们会写m/I have a [cat|dog|bird]/ 之类的东西,却没有意识到它与m/I have a [abcdgiort|]/ 相同(因为没有括号,所以不会捕获任何内容),并且想知道为什么他们的程序会抱怨$1 是一个未初始化的值。

这是一个常见的错误,所以如果您不知道其中的区别,请不要难过。现在您知道了,希望您能弄清楚代码的第二部分中需要更正的内容。

我希望这会有所帮助。

【讨论】:

  • 是的,感谢您花时间进行精彩的解释。第一部分奏效了。
  • @J-L 俗话说:你有问题。你决定用正则表达式来解决它。伟大的!现在你有两个问题。很好的答案。
猜你喜欢
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 2014-02-27
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多