使用Perl正则表达式重叠文本替换

时间:2012-01-17 19:45:07

标签: regex perl

我有一个包含一堆句子的文本文件。句子包含空格(空格,制表符,新行)以分隔出由字母和/或数字组成的单词。 我想找到单词“123”或“-123”并在数字开始前插入一个点(。)。因此,所有出现的“123”和“-123”都将转换为“.123”和“-123”。

我正在尝试以下内容:

$line =~ s/(\s+-*123\s+)/getNewWord($1)/ge

其中$ line包含从文件中读取的行,而函数getNewWord将把点(。)放在匹配的单词中的适当位置。

但它不适用于有两个连续“123”的情况,如“123 123”。当第一个“123”被“.123”替换时,单词后面的空格已经匹配,第二个“123”不匹配,因为正则表达式引擎无法将前一个空格与该单词匹配。

任何人都可以帮我吗?谢谢!

5 个答案:

答案 0 :(得分:5)

我同意MRAB(并且他/她的回答为+1),但并不真正需要getNewWord功能。我将整个语句改为其中一个:

$line =~ s/((?:^|\s)-?)(123)(?=\s|$)/$1.$2/g;

$line =~ s/(?:^|(?<=\s))(-?)(123)(?=\s|$)/$1.$2/g;

$line =~ s/(?:^|(?<=\s)|(?<=\s-))(?=123(?:\s|$))/./g;

答案 1 :(得分:4)

它可能稍快(没有显式捕获)并且它允许没有前导/尾随空格的文件:

$ echo '123 -123 -123  123' | perl -pe's/(?:^|\s+)\K(?=-?123\b)/./g'
.123 .-123 .-123  .123

.放在-之后:

$ echo '123 -123 -123  123' | perl -pe's/(?:^|\s+)-*\K(?=123\b)/./g'
.123 -.123 -.123  .123

答案 2 :(得分:2)

尝试使用这样的正向前瞻:(\s+-*123)(?=\s)

答案 3 :(得分:1)

这让我想起了这个问题:Search html file for random string using regex,我发现(显示)对负面外观断言的良好用法,即匹配可选分隔符以避免部分匹配。

匹配-?123很简单,问题是

  1. 不匹配部分字符串
  2. 避免线路不匹配的开始/结束
  3. 避免移动\G锚点
  4. 执行可选短划线-?
  5. 的外观断言

    我没有设法解决#4,因为不支持可变长度的lookbehind断言,因此修复程序使用捕获组。

    请注意,此问题的其他一些答案并未解决这些问题。

    说明:

    非空白的负向lookbehind断言匹配空格和字符串的开头,并确保我们不匹配部分字符串。然后遵循捕获组中的可选短划线。匹配的结尾是嵌套的前瞻,我们必须匹配123后跟任何非空白的内容。

    <强>代码:

    use strict;
    use warnings;
    
    while(<DATA>) {
        s/(?<!\S)(-?)(?=123(?!\S))/$1./g;
        print;
    }
    
    __DATA__
    r 123 z123 "123" -1233 d123 123-123
    123 -123 -123 123 123
    

    <强>输出:

    r .123 z123 "123" -1233 d123 123-123
    .123 -.123 -.123 .123 .123
    

答案 4 :(得分:0)

还是这个?这并没有打扰空白,而是在perl 5.8上工作。

echo '123 -123 -123  123' | perl -pe's/(-)?(123)/$1.$2/g'