3

在 perl 中有很多次我想在匹配的另一个替换运算符完成后用它自己替换匹配的字符串。例如,我有一个应用程序,我需要在其中查找带引号的字符串并从中删除空格。一种方法是:

while($str =~ s/"([^"])+"//){
   $temp = $1;
   $temp2 = $temp;
   $temp =~ s/ /_/g;
   $str =~ s/$temp2/$temp1/;
}

这似乎也是可能的:

$str =~ s/"([^"])+"/replace_spaces($1)/gx;
sub replace_spaces(){
    $word = shift;
    $word =~ s/ /_/g;
    return $word;
}

有没有一种纯粹的正则表达式方法,通过某种方式在正则表达式中嵌套正则表达式?

4

3 回答 3

3

对于手头的特定任务,最好使用Text::ParseWords

#!/usr/bin/env perl

use strict; use warnings;
use feature 'say';
use Text::ParseWords;

my $input = q{This is "a t e s t " string. "Hello - world  !"};
my @words = shellwords $input;

for my $word ( @words ) {
    $word =~ s/ +//g;
    say "'$word'";
}

另请参阅如何拆分 [character] 分隔的字符串,除非在 [character] 内?

于 2012-06-27T14:26:29.580 回答
2

是的,您可以这样做,但在每种情况下,您都需要发明新的正则表达式。在这种情况下没有灵丹妙药。

您必须使用下划线更改空格,但不能全部更改,只有在引号分隔的子字符串内。您检查的最后一个条件是向前看和向后看断言,但这些检查并不容易制定。

例如:

$ perl -pe 's/(?<=")(\S+)\s+(?=.*")/$1_/g;'
a b "c d" e f
a b "c_d" e f

但这远非完美。这适用于最简单的情况。这不是一个解决方案,它只是一个想法的演示。

于 2012-06-27T14:36:13.783 回答
1

你可以试试:

   $str =~ s{"([^"]+)"}{do{(local$_=$1)=~y/ /_/;$_}}eg;

或者,为了更好的可读性:

   $str =~ s/
             "([^"]+)"     # all inside double quotes to $1
            / do{          # start a do block
                 local $_ = $1; # get a copy from $1
                 y| |_|;        # transliterate ' ' to '_'
                 $_             # return string from block
                }          # end the do block
            /xeg;

问候

rbo

于 2012-06-27T14:47:20.720 回答