如何匹配文本并将其替换为基于Perl匹配的计算值?

时间:2010-01-04 15:56:10

标签: regex perl

我有一个函数,称之为f,它接受​​一个字符串并返回一个字符串。

我的文件包含如下所示的行:

stuff:morestuff:stuff*:otherstuff:otherstuff*\n

冒号只显示为分隔符,*仅显示在每个单词的末尾。我想循环遍历文件并用f(stuff)替换所有东西*。上一行将转到

stuff:morestuff:f(stuff):otherstuff:f(otherstuff)\n

我可以用几行来做到这一点,但必须有办法在一个方面做到这一点。

修改 要清楚,通过f(stuff),我的意思是f调用“stuff”,而不是字符串“f(stuff)”。

4 个答案:

答案 0 :(得分:9)

如果你use the e option for s//那么右手表达式被评估为代码。所以这很简单:

$line =~ s/([^:]+)\*/f($1)/ge;

打破比赛:

  • (开始标记模式的一部分
  • [^:]表示除:
  • 之外的任何内容
  • +表示其中一个或多个,即一个或多个不是冒号的字符
  • )结束标记模式的一部分为$1
  • \*字面意思是*

这种模式依赖于*仅出现在每个单词末尾的事实。如果它可能出现在一个字段的中间,你需要调整一下这个模式。

或者,将模式放在一个完整的脚本中:

sub f {
    my $word = shift;
    $word =~ tr/a-z/A-Z/;
    return $word;
}

while (<>) {
    s/([^:]+)\*/f($1)/ge;
    print;
}

答案 1 :(得分:4)

我这样做:

#! /usr/bin/perl

use warnings;
use strict;

sub f { uc reverse $_[0] }

while (<DATA>) {
  chomp;

  my $out = join ":" =>
            map s/(stuff)\*$/$1/ ? f($_) : $_,
            split /:/;

  print $out, "\n";
}

__DATA__
stuff:morestuff:stuff*:otherstuff:otherstuff*
otherstuff
stuff
stuff*
stuff*:otherstuff*

输出:

stuff:morestuff:FFUTS:otherstuff:FFUTSREHTO
otherstuff
stuff
FFUTS
FFUTS:FFUTSREHTO

但如果您患有全身性遗尿症,请使用

while (<DATA>) {
  chomp;

  s/  (?:^|(?<=:))     # BOL or just after colon
      ([^:]*stuff)\*   # ending with 'stuff*'
      (?=:|$)          # at EOL or just before colon
  / f $1 /gex;

  print $_, "\n";
}

这是因为/e switch

  

/e将导致替换部分被视为完整的Perl表达式并在那时进行评估。

答案 2 :(得分:2)

 $string =~ s{ (^|:) ([^:*]+) \* }{$1 . f($2)}gxe;

应该够了。

答案 3 :(得分:0)

$a=~s/(^|:)([^*:]*)\*(?=(:|$))/\1f\(\2\)/g;

- 编辑 -

如果f()是一个函数,我没有看到在一行中做任何特殊原因。 split - process - join

def f(x):
    return x.upper()

a='stuff*:morestuff:stuff*:otherstuff:otherstuff*\n';

print ':'.join([f(x[:-1]) if x[-1]=='*' else x for x in a.strip().split(':')])

听起来和任务一样简单。我喜欢python;)