【问题标题】:Java regex match against src="abc" or src='abc'Java 正则表达式匹配 src="abc" 或 src='abc'
【发布时间】:2012-01-19 14:15:33
【问题描述】:

我处于严格的 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="" ...

如果也想替换空的,只需将正则表达式中的 + 切换到星号(我不想要那个)

请注意原始引号也在其中。

回答问题二看黑熊猫

【问题讨论】:

  • 第二个问题没看懂。有例子吗?
  • @AlanMoore 查看已编辑的问题

标签: java regex groovy


【解决方案1】:

我对问题 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 部分编译你的正则表达式时遇到了麻烦。我会继续尝试看看我的问题出在哪里。
  • 是的,我在 Netbeans 6.9.1 上使用 JDK 6
  • 这就是我所说的:P 太好了!为什么java代码中的所有反斜杠,而不是顶部。我猜它们不是必需的?
  • 它们是绝对必要的!您必须转义 Java 字符串中的反斜杠。模式是 [^\\1]。这些反斜杠中的每一个都需要另一个反斜杠来转义。
【解决方案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

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

【讨论】:

  • 发帖人希望能够在字符串中包含其他类型的引号。他希望能够解析 src='this is " some text'
  • 啊,我明白了。我很确定仅使用正则表达式是不可能的。再次更新我的答案....
  • 请注意,我说的是“仅使用正则表达式”。请参阅上面我编辑的答案。
  • 抱歉,@Hamidam 我的第一个答案不正确。杰夫沃克是正确的。请取消选中我的答案作为最佳答案,以便我删除它。对此感到抱歉。
【解决方案3】:

你可以试试这样的

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

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

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

【讨论】:

    【解决方案4】:

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

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

    第二部分没有纯正则表达式解决方案——至少在 Java 中没有。有关 Java 方式,请参见 this answer。因此,例如,如果您有这样的表:

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

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

    【讨论】:

      猜你喜欢
      • 2019-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多