我试图用'#'替换字符串中的所有数字,前提是它们没有特定的前缀。 这些数字可能会显示为单词的一部分,也可能单独显示为单词。
例如,使用ABC作为前缀,这是期望的结果。
输入:
sdkfjsd 12312981 sdkfjsdfhbnmawd 1298 ,smdfsdnfk2342423
sdlkfsdfs 20349 ABC1203912 2034234aac <-- ABC<number> stays, the other numbers do not
ABC1203912
结果(请注意,第2,3行的ABC带有数字):
sdkfjsd # sdkfjsdfhbnmawd # ,smdfsdnfk#
sdlkfsdfs # ABC1203912 #aac <-- ABC<number> stays, the other numbers do not
ABC1203912
我试着用正面背面的负面看法来做这件事:s/(?<!ABC)\d+/#/g
。
在这种情况下,只有ABC之后的第一个数字不会被替换,其余的将会被替换。
我的下一步是将字符串拆分为包含ABC\d+
的部分,并对其他部分执行简单替换。
如果不分成多个字符串,将会欣赏如何完成整个事情的任何建议。
谢谢!
编辑1:将aac移回正确的位置。 编辑2:我使用perl 5.8.5,以防这是相关的。由于与我无法控制的代码的兼容性问题,我无法更新到更新的版本。
答案 0 :(得分:3)
我不明白你的意思&#34;我的下一步是将字符串拆分为包含ABC\d+
的部分,然后对其他部分执行简单替换。&#34 ;,但看起来这不是你的主要问题。请让我知道。
要匹配前面没有关键字ABC
的每个数字,那么您可以使用此正则表达式:
(?<!ABC|\d)\d+
如果数字前面有ABC
或其他数字(从而阻止\d+
匹配,如果从数字中间开始,则会阻止匹配。
请注意,您的问题中有两部分字符串移动了。我只接受您使用的输入。
如果上述方法不起作用(例如,正则表达式引擎表示后视图中的图案不能是可变宽度,或沿着这些线条的某些东西),那么替代等价物是:
(?<!ABC)(?<!\d)\d+
答案 1 :(得分:1)
它并不完全清楚你想要什么,尤其是因为2034234aac
字段在你的例子中被奇怪地修改过。
但是,对你自己的负面观察的这种修改可能会有用。请注意,它保留了以ABC
开头的完整任何序列,例如ABCX1234
。目前尚不清楚这是否是正确的行为。
use strict;
use warnings;
my $s = <<'__END_TEXT__';
sdkfjsd 12312981 sdkfjsdfhbnmawd 1298 ,smdfsdnfk2342423
sdlkfsdfs 20349 ABC1203912 2034234aac <-- ABC<number> stays, the other numbers do not
ABC1203912
__END_TEXT__
$s =~ s/\b(?!ABC)[a-z]*\K\d+/#/gi;
print $s;
或者,对于早于10的Perl 5版本,请使用此
$s =~ s/\b((?!ABC)[a-z]*)\d+/$1#/gi;
<强>输出强>
sdkfjsd # sdkfjsdfhbnmawd # ,smdfsdnfk#
sdlkfsdfs # ABC1203912 #aac <-- ABC<number> stays, the other numbers do not
ABC#
答案 2 :(得分:0)
你需要使用“零宽度负向后观断言”:只有在没有紧接的情况下才会匹配。
EG。匹配不在ABC
之前的数字:
(?<!ABC)\d
你已经有了这个,但下一步是匹配前缀和多个数字:
(?<!ABC)\d+
没有直接帮助,因为你需要不匹配。
稍微改一下这个问题:
替换不在前缀后面的数字和一个或多个数字
IE中。在“ABC123”中你不想替换1,2或3.我们可以将零宽度负向后看断言扩展为包括数字:
(?<!ABC\d+)\d
因此也排除了前缀后面的数字。
NB 这假设Perl支持可变宽度的lookbehinds:肯定是正则表达式的第一个扩展,包括它们必须固定宽度的lookbehinds,但它已经有一段时间了我认真使用Perl正则表达式,所以我假设Perl正则表达式实现已经扩展到与其他平台相匹配。
编辑:哎呀,s /正面/负面/外观。