perl regex删除引号对之间的任何内容

时间:2014-02-23 17:25:56

标签: regex perl quotes

我有一个字符串,我想删除一对引号之间出现的任何东西,只需用两个引号替换它。现在我有:

$string =~ s/'.*?'/''/g;

但是,这并不包括字符串中有引号的情况,例如:

$string = "'This is Joe\'s car'";

我希望这是"''",但它真的最终成为"''s car'"

无论如何要删除最外面的引号之间的所有内容?谢谢!

4 个答案:

答案 0 :(得分:2)

你通过让正则表达式非贪婪来要求它。话说:

$string =~ s/'.*'/''/g;

应该产生预期的结果。

答案 1 :(得分:2)

正如已经说过的,这不是一项微不足道的任务。除非字符串中有明确的黑色滑动表示引号不是平衡对的一部分,否则将无法直接确定平衡对的位置。这需要编写使用单引号背后的英语语言规则来执行此操作,即使这样,也可能会出现边缘情况。

一种可能接近的方法是,如果你使用负向前瞻并查看断言,要求起始引号不要在单词字符之前,并且结尾引号不能跟随一个。但是,即使这个要求也会因多个所有权而失败,如下面脚本中的最后一个例子所示:

use strict;
use warnings;

while (<DATA>) {
    chomp(my $src = $_);
    chomp(my $test = <DATA>);

    $src =~ s/(?<!\w)'(.*?)'(?!\w)/'<$1>'/g;

    print ($src eq $test ? 'matches  - ' : 'no match - ');
    print $src, "\n";
}


__DATA__
This is just a normal sentence.
This is just a normal sentence.
'This is Joe's car'
'<This is Joe's car>'
She said, "He said, 'Hurry up.'"
She said, "He said, '<Hurry up.>'"
This is 'special.'  That is also 'special.'
This is '<special.>'  That is also '<special.>'
'These are players' cars'
'<These are players' cars>'

答案 2 :(得分:0)

你可以试试这个正则表达式:

$string =~ s/'.*?(?<!\\)'/''/g;

但是这不适用于输入hey 'joe \'car

答案 3 :(得分:0)

您可以尝试使用内置模块Text::Balanced及其extract_delimited()功能。在列表上下文中,它返回引号,前缀和提醒之间的文本,因此您可以检查它们并删除要跳过的部分:

#!/usr/bin/env perl

use warnings;
use strict;
use Text::Balanced qw<extract_delimited>;

my $result;

my $string = "Before quotes 'This is Joe\\'s car' After quotes 'Last content' End";

while ( my @r = extract_delimited($string, q|'|, q|[^']*|) ) { 
    $result .= $r[-1] || ''; 
    if ( ! defined $r[0] ) { 
        $result .= $r[1];
        last 
    }   
    else {
        $result .= "''";
    }   
    $string = $r[1];
}

printf qq|%s\n|, $result;

请注意,我使用双反斜杠来转义单引号,因为perl在处理之前会自动转义所有单引号。另请注意,开头的转义单引号,如:

my $string = "Before \\'quotes 'This is Joe\\'s car';

也不起作用。我知道这很奇怪,但它可以在大多数简单的情况下工作。试试吧。

运行测试,如:

perl script.pl

产量:

Before quotes '' After quotes '' End