Regex 搜索并用捕获替换正则表达式

Regex 搜索并用捕获替换正则表达式,regex,perl,Regex,Perl,我有一个很长的文本文件,我想大部分保持不变,但某些短语需要翻译。这不完全是一个干净的搜索和替换。。。例如,我需要更改此事件的每个事件 lis r3, ha16(aLabel) ……在这方面: lis r3, aLabel@ha 也就是说,我需要找到整个ha16aLabel,从中捕获aLabel,该aLabel可以是到终止端paren的任何标识符文本,然后发送一个替换捕获的文本,后跟@ha 我已经找到了很多perl搜索和替换的例子,但我没有遇到任何与我需要的完全相同的东西,其他提到“perl”

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

lis r3, ha16(aLabel)
……在这方面:

lis r3, aLabel@ha
也就是说,我需要找到整个ha16aLabel,从中捕获aLabel,该aLabel可以是到终止端paren的任何标识符文本,然后发送一个替换捕获的文本,后跟@ha


我已经找到了很多perl搜索和替换的例子,但我没有遇到任何与我需要的完全相同的东西,其他提到“perl”和“capture”的帖子似乎也没有解决我的问题。。。或者他们真的这么做了,我太蠢了,没有意识到这一点。

你可以这样做:

#!/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)
如果两个字母中的第一个元素等于lo,则使用@l,如果不是,则使用这两个字母作为@扩展名,例如在我的示例文本中使用@ha或@ot


我认为这可以改进为一行,但我会这样做:

$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///都将告诉perl进行查找 并替换。如果有,则$1是第一组括号中的匹配项 如果超过一个,我们会有2美元等等。最后的gi说要替换 在全局范围内,在替换第一个匹配项后不要停止,并且不区分大小写。

类似

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;
}

使用?关闭贪婪,即。几乎匹配任何字符,+表示一个或多个字符

它总是ha16,或者可能有其他模式,或者它总是2个字母和2个数字?@Prix-我想要一个通用的解决方案,但在这个特殊情况下,我需要搜索、捕获和替换两个模式:ha16identifier->identifier@ha和lo16identifier->identifier@l. 不,这不是打字错误,第二次转换会在“lo”中删除“o”。第二次转换可以在必须保留的同一行上有字符,但第一次转换不能。为什么:不起作用?它清除了标识符_globvar.Aha。。。显然,你不能在正则表达式中使用$1,因为它是一个正则表达式元字符,我已经更新了代码来反映这一点\1@RobbertWijtman-这也是一个很好的解决方案,一旦通过编辑进行修复。这是一个很棒的解决方案,非常感谢。我完成的脚本是:您在40分钟内将我的perl正则表达式功能扩展了4000%。@phonetagger很高兴它能为您工作,我一直在玩e修饰符,它很糟糕。@phonetagger顺便问一下,这个修饰符也应该被修复吗-8r1No、ha16、hi16和lo16修饰符是LLVM汇编程序的方言,用于GCC汇编程序使用的内容:@ha、@hi和@l。它们指定应该进入寄存器的标签/标识符地址部分,因为在RISC代码中,不能在一条指令中加载整个32位。因此@ha和@hi加载最上面的16位,而@l加载最下面的16位。-8r1不是指定地址的标签/标识,它只是寄存器r1偏移量-8处的内存内容。@phonetagger我看到了,谢谢你让我知道,这看起来很熟悉,但我从来没有想过可能是哈哈。
my %map = (
    ha => '@ha',
    hi => '@hi',
    lo => '@l'
);

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