我有一个包含一堆句子的文本文件。句子包含空格(空格,制表符,新行)以分隔出由字母和/或数字组成的单词。 我想找到单词“123”或“-123”并在数字开始前插入一个点(。)。因此,所有出现的“123”和“-123”都将转换为“.123”和“-123”。
我正在尝试以下内容:
$line =~ s/(\s+-*123\s+)/getNewWord($1)/ge
其中$ line包含从文件中读取的行,而函数getNewWord将把点(。)放在匹配的单词中的适当位置。
但它不适用于有两个连续“123”的情况,如“123 123”。当第一个“123”被“.123”替换时,单词后面的空格已经匹配,第二个“123”不匹配,因为正则表达式引擎无法将前一个空格与该单词匹配。
任何人都可以帮我吗?谢谢!
答案 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
很简单,问题是
\G
锚点-?
我没有设法解决#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'