迭代ArrayList和String同时进行替换正则表达式

时间:2013-09-18 14:32:43

标签: java regex arraylist

我正在输入一个带有大量标签的输入HTML文件,如:

<h2 id="head-3d7e87e90500d3645e1f578a2b0fd6b4f7bd4ccf">

head-3d7e87e90500d3645e1f578a2b0fd6b4f7bd4ccf是一些随机值。

我在ArrayList中拥有所有必要的替换,使它们看起来像,例如

<h2 id="correctAnchor"> 

但我循环通过ArrayList&amp;在HTML上(解析为String)但它总是替换最后一个值:

    for (String temp2 : myAnchorLinks) {
        Pattern h2Pattern = Pattern.compile("<h2.*?>");
        Matcher h2Matcher = h2Pattern.matcher(replaceAllTags);
        if (h2Matcher.find()){
            replaceAllTags = replaceAllTags.replace("<h2 id=.*?>", "<h2 id="+temp2+">");        
        }

     }

任何想法我做错了还是有更好的方法?

“什么是维基?”

我无法发布所有HTML,但它看起来像:

ArrayList = {#blah1,#blah2,#blah3};

5 个答案:

答案 0 :(得分:2)

Map< String, String > replacements = new hashMap<>();
fillReplacements( replacements ); // Create associations between old and new IDs
// maybe from a properties file
for( map.Entry< String, String > e : replacements.entries()) {
   htmlSource = htmlSource.replaceAll( e.getKey(), e.getValue());
}

答案 1 :(得分:2)

您的第一个也是最关键的错误是使用replace()而不是replaceFirst()

replace()替换纯文本(非正则表达式)
replaceAll()replaceFirst()使用正则表达式查找要替换的匹配项

试试这个:

replaceAllTags = replaceAllTags.replaceFirst("<h2 id=.*?>", "<h2 id="+temp2+">");        

答案 2 :(得分:1)

如果您有Matcher,则应使用它,而不是使用String方法在幕后创建新的Matcher

Pattern h2Pattern = Pattern.compile("<h2.*?>");
Matcher h2Matcher = h2Pattern.matcher("");
for (String temp2 : myAnchorLinks) {
    h2Pattern.reset(replaceAllTags);
    replaceAllTags = h2Matcher.replaceAll("<h2 id="+temp2+">");
}

更新:我想,现在我知道你要做什么了:

Pattern h2Pattern = Pattern.compile("<h2.*?>");
Matcher m=p.matcher(replaceAllTags);
StringBuffer sb=new StringBuffer();
for(Iterator<String> it=myAnchorLinks.iterator(); it.hasNext() && m.find(); ) {
  m.appendReplacement(sb, "<h2 id="+it.next()+">");
}
m.appendTail(sb);
replaceAllTags=sb.toString();

这会从您的列表中为您的模式的每个匹配项分配另一个String。但是如果列表中的匹配项和元素数不匹配,您应该关心该怎么做。在我的例子中,它停在任何较小的东西上。

答案 3 :(得分:0)

正则表达式总是尽可能地匹配。所以,如果你有像

这样的字符串
<hello world="this"/> is such a nice <place/>

并将其与正则表达式<hello world=.?>匹配将返回整个字符串,因为它以“&gt;”结尾 - 不仅仅是你预期的第一部分。

你的正则表达式应为<h2 id=[^>]*>,然后匹配在“&gt;”处停止。

如果你想测试你的正则表达式,这里有一个good regex tester,它还提供了如何在Java中转义正则表达式。

答案 4 :(得分:0)

可能你正试图做这样的事情:

// Original String
String HTML="aslasasd <h2 id=\"head-abcdefg\">   <h2 id=\"head-hij5345345345n\">";

// Ids to replace secuentially
String[] ids ={"#id1","#id2"};

// Replace pattern
Pattern pattern = Pattern.compile("<h2[^<>\"']id=\"([^\"]*)\"");
Matcher matcher = pattern.matcher(HTML);
int i = 0;

// Loop for each id that match and replace the ramdom id with the next
// id in the list.
while(matcher.find()){
    HTML = HTML.replace(matcher.group(1),ids[i]); // replace Id
    i++;
    if (i > ids.length){
        break; // No more ids to replace
    }
}

// Replaced String
System.out.println(HTML);