如何在Perl中提取用双引号括起来的子字符串?

时间:2009-09-28 01:40:18

标签: regex perl

我是Perl和正则表达式的新手,我很难提取用双引号括起来的字符串。例如,

"Stackoverflow is

awesome"

在我提取字符串之前,我想检查它是否是变量中整个文本行的结尾:

if($wholeText =~ /\"$/)   #check the last character if " which is the end of the string
{
   $wholeText =~ s/\"(.*)\"/$1/;   #extract the string, removed the quotes
}

我的代码不起作用;它没有进入if条件。

5 个答案:

答案 0 :(得分:7)

你需要这样做:

if($wholeText =~ /"$/)
{
    $wholeText =~ s/"(.*?)"/$1/s;
}
除非您应用.修饰符,否则

/s与换行符不匹配。

没有必要像你一样逃避引号。

答案 1 :(得分:4)

上面推荐在正则表达式中使用“m”标志的海报是正确的,但是提供的正则表达式不会很好用。当你说:

$wholeText =~ s/\"(.*)\"/$1/m;   #extract the string, removed the quotes

...正则表达式太“贪婪”,这意味着(。*)部分会吞噬过多的文本。如果您有这样的样本:

"The quick brown fox," he said, "jumped over the lazy dog."

...然后上面的正则表达式将捕获从“The”到“dog。”的所有内容,这可能不是你想要的。有两种方法可以使正则表达式变得不那么贪婪。哪一个更好,与你如何选择处理字符串中的额外“标记”有关。

一:

$wholeText =~ s/\"([^"]*)\"/$1/m;

二:

$wholeText =~ s/\"(.*?)\"/$1/m;

在One中,正则表达式说“从引用开始,然后找到所有不是引用的内容并记住它,直到你看到另一个引用。”在二,正则表达式说“从引用开始,然后找到所有内容,直到找到另一个引用。”额外的?在()内部告诉正则表达式处理器不要贪心。不考虑字符串中的引用转义,两个正则表达式应该表现相同。

顺便说一句,这是解析CSV(“逗号分隔值”)文件时的一个经典问题,所以查找一些引用可能会对你有所帮助。

答案 2 :(得分:3)

如果要将匹配锚定到字符串的最末端(不是行,整个字符串),请使用\ z锚点:

 if( $wholeText =~ /"\z/ ) { ... }

你不需要保护条件。只需在替换中使用正确的正则表达式。如果它与正则表达式不匹配,则不会发生任何事情:

 $wholeText =~ s/"(.*?)"\z/$1/s;

我认为你真的有一个不同的问题。你为什么要把它锚到字符串的末尾?你想避免哪些问题?

答案 3 :(得分:1)

对于多行字符串,您需要在搜索模式中包含“m”修饰符。

if ($wholeText =~ m/\"$/m) # First m for match operator; second multi-line modifier
{
     $wholeText =~ s/\"(.*?)\"/$1/s;   #extract the string, removed the quotes
}

您还需要考虑是否允许在字符串中使用双引号,如果允许,则使用哪种约定。主要的是反斜杠和双引号(也是反斜杠反斜杠),或字符串中的双引号双引号。这些使你的正则表达式稍微复杂化。

@chaos的回答使用's'作为多行modifier。两者之间存在细微差别:

  
      
  •   
     

将字符串视为多行。也就是说,将“^”和“$”从匹配字符串的开头或结尾改为匹配字符串中任何一行的开头或结尾。

     
      
  • 取值
  •   
     

将字符串视为单行。也就是说,改变“。”匹配任何字符,甚至是换行符,通常它不匹配。

     

一起使用,作为/ ms,他们让“。”匹配任何字符,同时仍允许“^”和“$”分别匹配字符串中的换行符之后和之前。

答案 4 :(得分:0)

假设您在引号中包含一个子字符串,则将其提取出来:

s /。“(。?)”。* / $ 1 /

上面的答案(s /"(.*?)"/$ 1 / s)只会删除引号。

测试代码:

my $text = "no \"need this\" again, no\n";
my $text2 = $text;
print $text;
$text2 =~ s/.*\"(.*?)\".*/$1/;
print $text2;
$text =~ s/"(.*?)"/$1/s;
print $text;

输出:

no "need this" again, no
need this
no need this again, no