当前位置: 首页 > 知识库问答 >
问题:

使用String.replaceFirst(regexp,"1美元")得到匹配的子字符串时得到空字符串,正则表达式有什么问题?

王棋
2023-03-14

我想将ANSI转义序列转换为IRC颜色序列。

所以我写了一个正则表达式1\e\[([\d;])? m,但是,shell_output_string.replaceFirst("\\e\\[([\\d;])? m","1美元")将返回匹配的子串和其余不匹配的子串。

然后我编写了正则表达式2<code>*\e\[([\d;])?m、 *,希望它能匹配整个字符串并用匹配的子字符串替换,但是,replaceFirst(“.\\e\\[([\\d;])?m、 *“,“$1”)返回空字符串,但是否匹配(“.\\e\\[([\\d;])?m、 *”是否<code>true。此正则表达式有什么问题?

下面这个问题和这个问题很像:Pattern/Matcher group()在Java中获取子串?

示例代码

import java.util.regex.*;
public class AnsiEscapeToIrcEscape
{
    public static void main (String[] args)
    {
//# grep --color=always bot /etc/passwd
//
//bot:x:1000:1000:bot:/home/bot:/bin/bash
byte[] shell_output_array = {
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K  (#1 - #11)
0x62, 0x6F, 0x74,   // bot  (#12 - #14)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#15 - #20)
0x3A, 0x78, 0x3A, 0x31, 0x30, 0x30, 0x30, 0x3A, 0x31, 0x30, 0x30, 0x30, 0x3A,   // :x:1000:1000:    (#21 - #33)
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K  (#34 - #44)
0x62, 0x6F, 0x74,   // bot  (#45 - #47)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#48 - #53)
0x3A, 0x2F, 0x68, 0x6F, 0x6D, 0x65, 0x2F,   // :/home/  (#54 - #60)
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K  (#61 - #71)
0x62, 0x6F, 0x74,   // bot  (#72 - #74)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#75 - #80)
0x3A, 0x2F, 0x62, 0x69, 0x6E, 0x2F, 0x62, 0x61, 0x73, 0x68, // :/bin/bash   (#81 - #90)
};
        String shell_output = new String (shell_output_array);
        System.out.println (shell_output);
        System.out.println ("total " + shell_output_array.length + " bytes");

        final String CSI_REGEXP = "\\e\\[";
        final String CSI_SGR_REGEXP_First = CSI_REGEXP + "([\\d;]+)?m";
        final String CSI_SGR_REGEXP = ".*" + CSI_SGR_REGEXP_First + ".*";

        System.out.println (shell_output.replaceFirst(CSI_SGR_REGEXP_First, "$1"));
        System.out.println (shell_output.replaceFirst(CSI_SGR_REGEXP, "$1"));
    }
}

共有2个答案

钱跃
2023-03-14
    The API of String's replaceFirst says :


     replaceFirst

    public String replaceFirst(String regex,
                               String replacement)

        Replaces the first substring of this string that matches the given regular expression with the given replacement.

        An invocation of this method of the form str.replaceFirst(regex, repl) yields exactly the same result as the expression

            Pattern.compile(regex).matcher(str).replaceFirst(repl)

        Note that backslashes (\) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string; see Matcher.replaceFirst(java.lang.String). Use Matcher.quoteReplacement(java.lang.String) to suppress the special meaning of these characters, if desired.

        Parameters:
            regex - the regular expression to which this string is to be matched
            replacement - the string to be substituted for the first match 
        Returns:
            The resulting String 
        Throws:
            PatternSyntaxException - if the regular expression's syntax is invalid
        Since:
            1.4
        See Also:
            Pattern



Please read the Note Part which specifies that the \ and $ may cause the result to be different.
You can use Pattern and Matcher instead.

Example  
public class RegexMatches
{
    public static void main( String args[] ){

      // String to be scanned to find the pattern.
     // String line = "This order was placed for QT3000! OK?";
     // String pattern = "(.*)(\\d+)(.*)";

      byte[] shell_output_array = {
              0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K  (#1 - #11)
              0x62, 0x6F, 0x74,   // bot  (#12 - #14)
              0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#15 - #20)
              0x3A, 0x78, 0x3A, 0x31, 0x30, 0x30, 0x30, 0x3A, 0x31, 0x30, 0x30, 0x30, 0x3A,   // :x:1000:1000:    (#21 - #33)
              0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K  (#34 - #44)
              0x62, 0x6F, 0x74,   // bot  (#45 - #47)
              0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#48 - #53)
              0x3A, 0x2F, 0x68, 0x6F, 0x6D, 0x65, 0x2F,   // :/home/  (#54 - #60)
              0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K  (#61 - #71)
              0x62, 0x6F, 0x74,   // bot  (#72 - #74)
              0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#75 - #80)
              0x3A, 0x2F, 0x62, 0x69, 0x6E, 0x2F, 0x62, 0x61, 0x73, 0x68, // :/bin/bash   (#81 - #90)
              };
      String line = new String (shell_output_array);
      //String pattern = "(.*)(\\d+)(.*)";
      final String CSI_REGEXP = "\\e\\[";
      final String CSI_SGR_REGEXP_First = CSI_REGEXP + "([\\d;]+)?m";
      final String CSI_SGR_REGEXP = ".*" + CSI_SGR_REGEXP_First + ".*";

      // Create a Pattern object
      Pattern r = Pattern.compile(CSI_SGR_REGEXP);

      // Now create matcher object.
      Matcher m = r.matcher(line);
      while (m.find()) {
         System.out.println(m.start() + "  " + m.end());
         System.out.println("Found value: " + m.group());
      } 
   }
}
邹高峻
2023-03-14

正则表达式是贪婪的 - 也就是说,每个模式都会尝试尽可能多地匹配输入。

这意味着,当模式以.*开头时,该部分模式将尝试覆盖尽可能多的输入文本-因此有效地迫使模式的其余部分尝试从输入字符串的末尾开始向前查找匹配项。

那么,字符串末尾的其余模式的第一个匹配项是什么(或者,如果您愿意,匹配的最后一个子字符串是什么)?它位于输入的倒数第二行,仅由^[m组成

这是匹配的,因为模式的整个([\d;])部分由以下选项可选。

反过来,这意味着,由于最终表达式没有数字或;,$1组为空 - 因此您将获得空字符串输出。

至少,这是我在没有靠近Java机器进行测试的情况下得出的结论。希望有帮助。

 类似资料:
  • 我想将ANSI转义序列转换为IRC颜色序列。 所以我写了一个正则表达式1,然而,将同时返回匹配的子字符串和其余不匹配的子字符串。 然后我写了正则表达式2,希望它能匹配整个字符串,并用匹配的子字符串替换,然而返回空字符串,但是,这个正则表达式有什么问题? 下面的问题与这个问题非常相似:pattern/matcher group()在Java中获取substring? 示例代码

  • 问题内容: 我在尝试将我的javascript regex经验转移到Python时遇到了麻烦。 我只是想让它工作: …但是它打印无。如果我做: 它匹配…默认情况下是否匹配字符串的开头?当匹配时,如何使用结果? 我如何进行第一场比赛?是否有比python网站提供的文档更好的文档? 问题答案: 隐式添加到您的正则表达式的开头。换句话说,它仅在字符串的开头匹配。 将在所有位置重试。 一般来说,建议您在需

  • 问题内容: 我在用Python将字符串中的数字匹配时遇到麻烦。尽管应该明确匹配,但甚至不匹配 或仅匹配。我的监督在哪里? 问题答案: 阅读文档:http : //docs.python.org/2/library/re.html#re.match 如果在零个或多个字符 开头 的 字符串 您要使用(或)

  • 我有一些xml文件,希望删除除特定字符串以外的所有内容。 StackOverflow上还有很多类似的问题,但都不适用于我的文件,在尝试了几个小时不同的正则表达式后,我想寻求帮助。 到目前为止,部分成功但并非完全成功的最接近的正则表达式是: xml文件的示例: 我使用regex101,因此可以将示例粘贴在那里,以了解为什么rex只能部分工作。简而言之,它与第一次出现的不匹配,但与第二次出现的匹配。我

  • 问题内容: 我需要一个匹配但不匹配的正则表达式 我希望它只匹配foo及其周围的所有内容,只要不跟在bar后面即可。 我尝试使用此方法:这是相当接近的,但它匹配。负面的眼光需要匹配任何东西,而不仅仅是障碍。 我使用的特定语言是Clojure,它在后台使用Java正则表达式。 编辑:更具体地说,我也需要它通过但不是。 问题答案: 尝试: 测试: 正则表达式说明 其他正则表达式 如果您只想排除紧接其后的

  • 问题内容: 我会在开头提到这个问题,尽管我离正则表达式专家很远,但是它们对我来说并不完全陌生。对于我来说,构建正则表达式来搜索特定字符串中的模式通常不是问题,但是我有一个(也许是?)独特的情况。 我有一组价值观,例如: 028938 DEF567987 390987.456 GHI345928.039 我想匹配一组特定的字符串,例如: 完全由6位数字组成的字符串 字符串,由正好6位数字,十进制组成