1

我有一个很长的文本文件,我希望大部分内容保持不变,但某些短语需要翻译。这不完全是一个干净的搜索和替换......例如,我需要更改每次出现的这个......

lis r3, ha16(aLabel)

...进入这个:

lis r3, aLabel@ha

即我需要找到整个ha16(aLabel),从中捕获aLabel(可以是任何标识符文本,直到终止的结尾括号),然后发出捕获文本的替换,然后是@ha.

我找到了很多 perl 搜索和替换的例子,但我没有遇到过我需要的东西,其他提到“perl”和“捕获”的帖子似乎并没有解决我的问题。 . 或者也许他们这样做了,我太愚蠢了,没有意识到这一点。

4

3 回答 3

3

你可以这样做:

#!/usr/bin/perl

use strict;
use warnings;

my $text = 'lis r3, ha16(L_.str10) some more text blah lis r3, lo16(identifier) some more text blah lis r3, ot16(identifier)';
$text =~ s/(\w{2})\d{2}\(([\w\.]+)\)/$1 eq 'lo' ? $2 . '@l' : $2 . '@' . $1/gie;
print $text;

也可以写成:

#!/usr/bin/perl

use strict;
use warnings;
while (<DATA>) {
     s/(\w{2})\d{2}\(([\w\.]+)\)/$1 eq 'lo' ? $2 . '@l' : $2 . '@' . $1/gie;
     #you can also print out the result of the replacement.
     #print $_;
}

__DATA__
lis r3, ha16(L_.str10) 
some more text blah lis r3, lo16(identifier) 
some more text blah lis r3, ot16(identifier)

简单来说,e修饰符允许您使用正则表达式右侧的代码来替换模式。有关更详细的解释,您可以阅读此问题。

在此示例中,我(\w{2})\d{2}用于匹配括号内标签之前的扩展名,并将 2 个字母分组以供以后使用,并使用([\w\.]+)这意味着任何字母数字字符加上下划线和点,以匹配您的标签。

在右边,我正在做一个三元运算符来定义扩展:

$1 eq 'lo' ? $2 . '@l' : $2 . '@' . $1

如果第一个元素是 2 个字母,lo则使用@l,如果不是,则使用 2 个字母@extension,例如@ha@ot在我的示例文本中。

现场演示。

于 2013-08-08T23:19:27.937 回答
2

我认为这可以改进为一行,但这就是我的做法:

$val = "lis r3, ha16(L_.str10)";
if ($val =~ /ha16\((.*?)\)/) {
    # $1 now contains the extracted text
    $capture = $1;
    $val =~ s/ha16\(.*?\)/$capture\@ha/gi;
}

所涉及的正则表达式的解释:

ha16\((.*?)\)

ha16\(基本上说“任何以”开头的文本ha16(。被(转义,因为它是一个正则表达式关键字

(.*?)意思是“捕获与其中的模式匹配的()所有内容。 说”匹配任何字符(即 )的零.*?个或多个(即*.?

\)说“一旦达到这一点,停止匹配”(这是因为我们使用了非贪婪?

和替换:

s/ha16\(.*?\)/$1\@ha/gi

这种格式的任何东西:s/<something>/<something>/都会告诉 perl 进行查找和替换。The$1是第一组括号中的匹配项(如果有更多的话,我们将有 a$2等等)。最后gi说要替换全局(替换第一个匹配后不要停止),并且不区分大小写。

于 2013-08-08T23:22:55.710 回答
2

就像是..

use strict;
use warnings;

while (<>) {
     s/ha16\((.+)\)/$1\@ha/gi;
     print;
}

或者更好的是,为多次出现的变化使用映射。

my %map = (
    ha => '@ha',
    hi => '@hi',
    lo => '@l'
);

while (<>) {
   s/(\w{2})16\((.+)\)/$2$map{$1}/gi;
   print;
}

使用 消除贪心?.匹配几乎任何字符,+表示一个或多个。

于 2013-08-08T23:32:21.033 回答