【问题标题】:string: replace "(" with "\("字符串:用“\(”替换“(”
【发布时间】:2011-06-13 23:22:36
【问题描述】:

我必须向 bash 发送一个字符串,其中包含一个转义序列。例如,我必须将“(”之类的特殊字符替换为“(”),因为 bash else 会引发错误。我喜欢

public class escape {
    public static void main(String args[]) {
        System.out.println("\\");
        String s = "(foo)";
        System.out.println(s);
        s = s.replaceAll("(", "\\(");
        System.out.println(s);
    }
}

没有运气。请帮忙!!

谢谢

【问题讨论】:

  • 请注意,如果注入攻击很重要或变得很重要,您仍然会受到注入攻击的影响。

标签: java regex string bash escaping


【解决方案1】:

String.replaceAll 使用正则表达式,这不是您想要的。只需使用String.replace

s = s.replace("(", "\\(");

【讨论】:

  • 最有趣的是,为了实现简单的字符串替换,它确实使用了正则表达式。 Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
  • >>更简单更快。 +1;不是真的“更快”
  • @bestsss:明天可能会更快。今天,它绝对更简单、更安全。
  • @cherouvim:我严重怀疑 String 会放弃使用 regExp 来实现。替换,除非它发生,否则它不会更快。另外,你需要现在运行你的代码,而不是明天。我确实意识到需要使用可用的标准 API,但是,我不同意它们总是“更安全”。同样,我发布的代码可以追溯到 1999 年左右的 RegExp (1.4) 和 CharSequence (1.5) 之前。
  • @bestsss:我想说,除非你想要使用正则表达式,否则使用在正则表达式方面不起作用的 API 会更安全,因为它是更容易不搞砸。
【解决方案2】:
s = s.replaceAll("\\(", "\\\\(");

【讨论】:

  • 除非 OP 真的想要使用正则表达式,为什么要让它变得复杂呢?
  • 我认为第二个参数仍然应该是"\\\(" - 它不是正则表达式。
  • 不,第二个参数是正确的 - 括号仍然需要在替换中进行转义。另外,我真的希望 cmets 允许代码格式化,所以我可以将这个问题解释为这个答案的附录。
  • 好的。知道了。您需要转义斜线,尽管它似乎没有真正的功能(除了转义$)。
  • @Jon Skeet:是的,在这种情况下 replace() 肯定更好。
【解决方案3】:

发生这种情况是因为 ( 是根据正则表达式语法的特殊字符(由 replaceAll 使用)。

在这种情况下,您应该听取 Skeet 的建议并改用“替换”,但为了让您了解正则表达式版本的工作原理,这里有一个固定示例:

public class test {
    public static void main(String args[]) {
        System.out.println("\\");
        String s = "(foo)";
        System.out.println(s);
        s = s.replaceAll("\\(", "\\\\(");
        System.out.println(s);
    }
}

【讨论】:

    【解决方案4】:

    查看所有 regexp 解决方案(String.replace(CharSequence, CharSequence) 也是 regexp impl. under the hold),这里有一段代码在其中一个 Util 类中存在了很长时间。 [这就是为什么它仍然使用 StringBuffer(旧时代)]

    public static String replace(String strToRepl,String orig,String repl){
        if (strToRepl==null) return null;
        int len=strToRepl.length();
        StringBuffer buf=null;
    
        int ind;
        int origLen=orig.length();
        int start=0;
    
        while (start<len&&(ind=strToRepl.indexOf(orig,start))>=0){
            if (buf==null) buf=new StringBuffer(len*3/2);
            buf.append(strToRepl.substring(start,ind)).append(repl);
            start=origLen+ind;
        }
    
        if (buf!=null){
            if (start<len)
                buf.append(strToRepl.substring(start));
            return buf.toString();
        }
    
        return strToRepl;
    }
    

    【讨论】:

    • 这比使用 .replace 有什么好处?是否更快?如果是,速度会快多少?在什么情况下?
    • 这总是应该比正则表达式更快。例如,如果没有替换[操作思想支持稀有到无替换],上述方法将快得多(并且也不进行分配)。代码也更容易(非常)容易被 JVM 内联。如果您真的需要类似领域的微基准测试,我想我可以执行它们。然而,RegExp 需要这样做,但还需要编译 RegExp(两者),在此过程中创建少量其他实例(分配)并最终生成相同数量的子字符串。这取决于要替换的字符串的长度...
    • ...我只是猜测并说 4-5 次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    • 2023-03-04
    • 2013-05-01
    • 1970-01-01
    • 2020-08-31
    • 2014-08-31
    相关资源
    最近更新 更多