我有一个函数,称之为f
,它接受一个字符串并返回一个字符串。
我的文件包含如下所示的行:
stuff:morestuff:stuff*:otherstuff:otherstuff*\n
冒号只显示为分隔符,*仅显示在每个单词的末尾。我想循环遍历文件并用f(stuff)替换所有东西*。上一行将转到
stuff:morestuff:f(stuff):otherstuff:f(otherstuff)\n
我可以用几行来做到这一点,但必须有办法在一个方面做到这一点。
修改 要清楚,通过f(stuff),我的意思是f调用“stuff”,而不是字符串“f(stuff)”。
答案 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;)