5

根据我在这里看到的(接受的答案),我似乎可以通过这样做来转义字符串:

string s = "Woolworth's";
string t = Regex.Escape(s);
MessageBox.Show(t);

...但是通过它,我发现 s 和 t 之间没有区别(我希望我会看到“Woolworth\'s”作为 t 的值,而不是两个 vars 的“Woolworth's”)。

我想,我可以做这样的事情:

    string s = "Woolworth's";
    s = s.Replace("'", "\'");

...etc., also escaping the following: [, ^, $, ., |, ?, *, +, (, ), and \

...但“一站式购物”解决方案会更可取。

更具体地说,我需要用户输入的字符串可以作为 Android arrays.xml 文件中的字符串值。

例如,它对此感到窒息:

<item>Woolworth's</item>

...这需要是这样的:

<item>Woolworth\'s</item>
4

4 回答 4

6

Regex.Escape()只转义正则表达式保留字符:

通过用转义码替换最小字符集(\、*、+、?、|、{、[、(,)、^、$、.、# 和空格)来转义它们。这指示正则表达式引擎按字面意思解释这些字符而不是元字符。


匹配/捕获要转义的字符的字符类(注意,某些字符在字符类中具有特殊含义,需要像\and一样进行转义-):

(['^$.|?*+()\\])

然后用反斜杠和对要转义的字符的引用替换它:

\\1

演示


在 C# 中:

string s = "Woolworth's";
Regex rgx = new Regex("(['^$.|?*+()\\\\])");

string t = rgx.Replace(s, "\\$1");
// Woolworth\'s

演示

于 2014-06-04T21:16:36.607 回答
3

Regex.Escape不适合这种情况

它是严格为正则表达式设计的,并且对于这种情况会逃逸太多太少- 试图将其硬塞到模型中可能会破坏其他值。(它不会转义',或者"因为这些字符在 .NET 正则表达式中没有特殊含义。)

这里相关的是字符串资源文件中的项目元素在从 XML 读取文本对文本(与格式相关)进行一些特殊解析:

如果字符串中有撇号或引号,则必须对其进行转义或将整个字符串括在另一种类型的封闭引号中。

因此,适合这种情况的转换很简单

s.Replace("'", "\'").Replace("\"", "\\\"")

或者

Regex.Replace(s, "['\"]", "\\$&")

(然后,假设 XML 是通过 DOM 或 LINQ to XML 正确构建的,XML 编码会在其他地方得到处理——尽管在使用格式化与混合内容样式时规则更复杂。)

于 2014-06-04T21:31:39.267 回答
1

有不同种类的字符转义。在您链接到的问题中,他们正在谈论正则表达式的转义,它们有自己的一组特殊字符。

如果您特别希望为 XML 转义文本,您可能需要查看 System.Xml 命名空间中的XmlConvert 类。有了它,您可以使用 XmlConvert.EncodeName 转义字符并使用 XmlConvert.DecodeName 检索字符:

    string s = "Woolworth's";
    string encoded = XmlConvert.EncodeName(s); // Value here is Woolworth_x0027_s
    string decoded = XmlConvert.DecodeName(encoded); // Value here is Woolworth's
于 2014-06-04T21:22:00.013 回答
1

“在一行代码中”实现某事的最佳方法是在某处编写一个方法,该方法可以正确完成工作,然后从那一刻起,每次调用该方法时,都将自己想象为“在一行代码中”代码”。

接受的答案似乎可以解决问题,但是对于换行等控制字符或由于各种原因可能无法打印的任何其他 unicode 字符,它将惨遭失败。

以下方法将等效于StringEscapeUtils.escapeForJava().

我发布它主要是为了让人们将来偶然发现这个问题,寻找这个非常常见问题的答案。

public static String escapeForJava( String value, boolean quote )
{
    StringBuilder builder = new StringBuilder();
    if( quote )
        builder.append( "\"" );
    for( char c : value.toCharArray() )
    {
        if( c == '\'' )
            builder.append( "\\'" );
        else if ( c == '\"' )
            builder.append( "\\\"" );
        else if( c == '\r' )
            builder.append( "\\r" );
        else if( c == '\n' )
            builder.append( "\\n" );
        else if( c == '\t' )
            builder.append( "\\t" );
        else if( c < 32 || c >= 127 )
            builder.append( String.format( "\\u%04x", (int)c ) );
        else
            builder.append( c );
    }
    if( quote )
        builder.append( "\"" );
    return builder.toString();
}
于 2015-03-16T08:58:25.517 回答