来自具有特殊表情符号的字符串的子串,String.IndexOf返回-1

时间:2014-06-13 07:35:09

标签: c# string unicode

我有一个带有特殊表情符号的字符串:

string test = "<textarea style='display:none;'>˃̣̣̥᷄⌓˂̣̣̥᷅  abcde";

我希望得到这个字符串的子字符串,如下所示:

string sub = test.Substring(test.IndexOf(">"));

(因为字符串“test”的第一个“&gt;”表示HTML代码的结尾)

(我想要的结果是˃̣̣̥᷄⌓˂̣̣̥᷅ abcde

但是,Substring方法返回错误(“StartIndex不能小于0”),这意味着没有'&gt;'在字符串'test。'中

所以我测试了类似下面的东西:

test.Contains(">");

返回'True。'

以下是我的问题:Contains方法表示字符串'test'包含'&gt;'在其中,但Substring方法无法正常工作......

如何从字符串'test'中获取正确的子字符串?

2 个答案:

答案 0 :(得分:1)

正如其他人已经说过的那样,IndexOf(">")执行文化敏感搜索。这意味着你必须记住,存在基本上是不同unicode字符组合的字符。

让我们看一下字符串的这一部分:;'>˃̣̣̥᷄⌓˂̣̣̥᷅

它包含以下unicode字符:

SEMICOLON (U+003B) 
APOSTROPHE (U+0027) 
GREATER-THAN SIGN (U+003E) 
MODIFIER LETTER RIGHT ARROWHEAD (U+02C3) 
COMBINING DOT BELOW (U+0323) 
COMBINING DOT BELOW (U+0323) 
COMBINING RING BELOW (U+0325) 
COMBINING MACRON-ACUTE (U+1DC4) 
SEGMENT (U+2313) 
MODIFIER LETTER LEFT ARROWHEAD (U+02C2) 
COMBINING DOT BELOW (U+0323) 
COMBINING DOT BELOW (U+0323) 
COMBINING RING BELOW (U+0325) 
COMBINING GRAVE-MACRON (U+1DC5) 

请注意,虽然它包含GREATER-THAN SIGN (U+003E >)字符,但请注意后面跟有MODIFIER LETTER RIGHT ARROWHEAD (U+02C3 ˃)个字符。此字符是所谓的spacing modifier letter,用于更改前一个或后一个字符的含义。

此行为与以下字符(COMBINING DOT BELOWCOMBINING RING BELOW)非常相似,这些字符为combining diacritical marks,但这些字符通常位于其修改的字符的顶部或下方(如您所见)可以在这里看到: ̣̣̥᷄⌓SEGMENT,由两个DOT BELOW,一个RING BELOW和一个MACRON_ACUTE修改。

因此,如果考虑组合字符(IndexOf(String)执行),那么您的字符串不包含字符串>(单个大于符号)。

要检查单个(未合并)字符,您可以使用IndexOf('>')(使用char代替string):

  

此方法执行序数(区域性不敏感)搜索,其中只有在Unicode标量值相同时才将字符视为与另一个字符等效。

test.IndexOf(">", StringComparison.Ordinal)


话虽如此,如果你想解析HTML,最好使用像Html Agility Pack这样的HTML解析器:

string html = "<textarea style='display:none;'>˃̣̣̥᷄⌓˂̣̣̥᷅  abcde</textarea>";
HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
htmlDoc.LoadHtml(html);
var value = htmlDoc.DocumentNode.SelectSingleNode("//textarea").InnerText;

value现在包含˃̣̣̥᷄⌓˂̣̣̥᷅ abcde

答案 1 :(得分:0)

在角色测试中使用单引号。

string sub = test.Substring(test.IndexOf('>'));

如果你想使用“strings”而不是'c'har,你需要指定一个stringComparison Type。

string test = "<textarea style='display:none;'>˃̣̣̥᷄⌓˂̣̣̥᷅  abcde"; 
string sub = test.Substring(test.IndexOf(">", StringComparison.Ordinal));
Console.WriteLine(test.IndexOf(">", StringComparison.Ordinal));
Console.WriteLine(sub);

string.IndexOf(string s)的默认行为是进行StringComparison.CurrentCulture区域敏感的比较。

String.IndexOf Method (String) (System) @ MSDN