我想在一个字符串上进行两次正则表达式替换,即用Java术语
myString.replaceAll(pattern1, replacement1).replaceAll(pattern2, replacement2);
但是,假设myString
可能很长,所以最好避免对它进行两次传递。这可以单程完成吗?
String pattern = ...;
String replacement = ...;
myString.replaceAll(pattern, replacement);
pattern
的明显候选人是pattern1 + "|" + pattern2
,但后来我看不到如何撰写replacement
。
为了简化,我们假设pattern1
和pattern2
的匹配不能相交,replacement1
不会引入pattern2
的任何新匹配。
答案 0 :(得分:1)
根据您使用的编程语言这一事实,您可以使用回调作为替换,并使用与两者匹配的RegExp,然后您将在回调函数中使用if语句检查匹配和替换的regexp它有适当的替代品。
答案 1 :(得分:1)
执行此操作的最简单方法是维护将字符串映射到其替换项的哈希。编写匹配任何键的匹配项,并将匹配的键传递给替换部分。有替换部分而不是拉入值。
在Perl中,这只会是:
my @keys = keys %hash;
my $alt = '\b(' . join("|", @keys) . ')\b';
s/($alt)/$hash{$1}/g;
等效的Java解决方案 - 就像所有东西一样 - 显着更长,但同样的方法也可以。
如果一个字符串是另一个字符串的起始子字符串,则会出现排序问题。
答案 2 :(得分:1)
与几乎所有其他正则表达式不同,Java不支持回调。但是,它确实暴露了一些允许您自己实现它们的低级API调用。这是一篇文章,展示了如何做到这一点:
Java Regex Replace with Capturing Group
正如您所指出的,您需要将模式合并为一个,但您还需要在其自己的捕获组中隔离每个模式,如下所示:
String bigPattern = "(" + pattern1 + ")|(" + pattern2 + ")";
(如果模式已经包含捕获组,这将改变编号方案;您将必须调整任何反向引用。我将假设除了您刚创建的那些之外没有捕获组。)
然后,在replacement()
方法中,您确定实际匹配的组,并相应地选择替换文本:
public String replacement()
{
if (group(1) != null)
{
return replacement1;
}
else if (group(2) != null)
{
return replacement2;
}
}
答案 3 :(得分:0)
正如@levu所说,这取决于编程语言。在Ruby中,你可以这样做:
ree-1.8.7-2010.02 > s
=> "hello world"
ree-1.8.7-2010.02 > s.gsub(/(hello|world)/) {|match| match == 'hello' ? 'hi there!' : 'universe!' }
=> "hi there! universe!"
当gsub在String中看到“hello”或“world”时,它会将该值发送到名为match的变量中的块。该块用“hi there!”替换“hello”,并用“universe!”替换任何其他值。