Java正则表达式匹配src =“abc”或src ='abc'

时间:2012-01-19 14:15:34

标签: java regex groovy

我在严格的Java环境中。

所以这个问题并不像在Tite中那么简单,我不是在试图解决我遇到的问题,而是为更好的知识提供更多的理论。

我感兴趣的是使用双引号或简单引号匹配src,但如果是双引号,则必须使用双引号关闭,同样适用于简单引用。

我知道我可以重复正则表达式,即:

String str = "src=\"hello/\" ... src='hello/' ..."

println str.replaceAll ("src=((\"[^\"]+\")|('[^']+'))", "src=$1")

我想做的是:

println s.replaceAll ("src=([\"'][^\"']+[\"'])", "src=$1")

但是,如果以双引号开头,则应在内容中允许使用简单引号,并且必须以双引号结束,而不是简单引用。

问题2:

是否可以使用相同类型的引用将其替换为所有? 是否可以说,对于这个匹配,替换为this2,为此,替换为that2。 如何在不每次生成新字符串的情况下实现此目的?

编辑Alan More,问题二的例子:

println "one ... two".replaceAll( "(one)", "1" ).replaceAll("(two)", "2");

更多沿着这些方面(不对)

println "one ... two".replaceMyMatches( "(one)[^\\w]+(two)", "\$1{1}, \$2{2}" ) // prints string : one{1}, two{2} 

我想要的是字符串:1,2

回答第一个问题从黑熊猫和杰夫沃克获得并改变了一点:

String str = "src=\"1.png\" ... src='2.jpeg' ... src=\"3.p'ng\" ... src='4.jpe\"g' ... src='' ... src=\"\" ..." ;

String regex = "src=(['\"])(.+?)\\1"; // closes with the quote that is in group 1

println str.replaceAll( regex, '''src=$1../new_path/$2$1''')

吐出:

src="../new_path/1.png" ... src='../new_path/2.jpeg' ... src="../new_path/3.p'ng" ... src='../new_path/4.jpe"g' ... src='' ... src="" ...

如果有人想要替换空的那些,只需将正则表达式中的+与星号切换(我不希望这样)

请注意原始引号也在。

回答问题二看黑熊猫

4 个答案:

答案 0 :(得分:2)

问题1的正则表达式是:

src=(['"])hello\1(Java字符串的双反斜杠)

它使用反向引用匹配第一个引号或双引号,然后匹配与第一个引号相同的字符。

因此,对于更一般的情况,我喜欢:

^src=(['"])(.*?)\1$

然后替换可能是这样的:

String regex = "^src=(['\"])(.*?)\\1$";
String newthing = "src=$2";

这是你想要的吗?基本上剥离引号,同时强制它们匹配?

由于精明的评论,我现在明白你希望引号互相逃避。像Perl这样的语言可以做到这一点,但它们不是通过正则表达式解析的。这种类型的东西属于一类需要实际解析的问题。 (不记得实际的术语)

您必须检查第2组并“断言”第1组不存在,而不是替换。注意到我在正则表达式中添加了开始和结束锚点。

类似于:

Pattern p = Pattern.compile("^src=(['\"])(.*?)\\1$");
Matcher m = p.matcher("src=\"what's up?\"");
if ( m.matches() ) {
    if ( m.group(2).contains(m.group(1)) ) {
        // fail, doesn't match
    }
}
// success, follows all of the rules

即使有更新,我也无法理解你在第二个问题中寻找的内容。如果我得到它,我会编辑这个答案。

答案 1 :(得分:2)

我对问题1的回答最初是不正确的。这是一个更新版本。

回答问题1.如果这个正则表达式可以帮助你: 模式是:

src=(['"])(.*?)\1

下面的代码解释了每一件。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Regex {

   public static void main(String[] args)
   {
      final String regex = "src=(['\"])" // the ' or the " is in group 1
              + "(.*?)" // match any character in a non-greedy fashion
              + "\\1"; // closes with the quote that is in group 1
      Pattern p = Pattern.compile(regex);

      Matcher m = p.matcher("src=\"hello/\"  ...   src='goodbye/'  ... "
              + "src='this has a \" in it'");

      while (m.find())
      {
         System.out.println("\nfound!");
         System.out.println("The quote was a " + m.group(1));
         System.out.println("the text was = " + m.group(2));
      }
   }
}

这给出了输出:

found!
The quote was a "
the text was = hello/

found!
The quote was a '
the text was = goodbye/

found!
The quote was a '
the text was = this has a " in it

至于第二个问题,你将不得不使用更多的代码。您可以创建自己的StringBuffer并随附。我使用地图来保存替换:

   public static void question2()
   {
      Pattern p = Pattern.compile("one|two");
      Map<String, String> replacements = new HashMap<String, String>();

      replacements.put("one", "1");
      replacements.put("two", "2");

      StringBuffer result = new StringBuffer();

      String text = "one ... two";

      Matcher m = p.matcher(text);

      while (m.find())
      {
         m.appendReplacement(result, replacements.get(m.group()));
      }

      m.appendTail(result);

      System.out.println(result.toString());

   }

输出:

1 ... 2

答案 2 :(得分:1)

你可以试试这样的事情

String str = "src=\"hello/\" ... src='hello/' ...";

System.out.println(str.replaceAll("src=([\"'])(.*?)\\1", "src='$2'"));

诀窍是在同一个正则表达式中使用\ 1重用第一个匹配的模式

答案 3 :(得分:0)

对于第一个问题,您可以使用此正则表达式:

"([\"'])(?:(?!\\1).)*\\1"

第二部分没有纯正则表达式解决方案 - 至少不是Java。有关Java方式,请参阅this answer。所以,例如,如果你有一个这样的表:

{ "one" => "1", "two" => "2" }

...您的replacement()方法会通过在表中查找替换字符串的动态部分,使用捕获组的内容作为键。