匹配正则表达式中的Unicode字符



我使用HttpClient类从网站检索字符串。web服务器以UTF-8编码发送它们。字符串的形式为abc | a,如果它们位于字符串的末尾,我想删除管道,空格和空格后的字符。

sText = Regex.Replace (sText, @"| .$", "");

按预期工作。现在,在某些情况下,管道和空格后面跟着另一个字符,例如smiley。字符串的形式是abc | 😉。上面的正则表达式不起作用,我必须使用

sText = Regex.Replace (sText, @"| ..$", "");

代替(两个点)。

我很确定这与编码和事实有关,笑脸符号在UTF-8中使用的字节比拉丁字符多,而且c#不知道编码。笑脸符号只是一个字符,即使它使用了更多的字节,所以在告诉c#正确的编码(或转换字符串)之后,第一个正则表达式应该在两种情况下都有效。

如何做到这一点?

就像评论中建议的那样,这个问题很难用Regex解决。你所说的"看起来像一件东西"。实际上是一个字母簇。相应的。net术语是"文本元素"。可以通过使用StringInfo.GetTextElementEnumerator来解析和迭代。

基于文本元素的一个可能的解决方案可以非常简单:我们只需要从输入字符串中提取最后3个文本元素,并确保它们引用管道,空格和最后一个可以是任何。请参阅以下建议的方法实施。

void Main()
{
var inputs = new[] {
"abc | a",
"abc | ab", // The only that shouldn't be trimmed
"abc | 😉",
"abc | " + "uD83DuDD75u200Du2642uFE0F" // "man-detective" (on Windows)
};

foreach (var input in inputs)
{
var res = TrimTrailingTextElement(input);
Console.WriteLine("Input : " + input);
Console.WriteLine("Result: " + res);
Console.WriteLine();
}
}
string TrimTrailingTextElement(string input)
{
// A circular buffer for storing the last 3 text elements
var lastThreeElementIdxs = new int[3] { -1, -1, -1 };

// Get enumerator of text elements in the input string
var enumerator = StringInfo.GetTextElementEnumerator(input);
// Iterate through the enitre input string,
// at each step save to the buffer the current element index
var i = -1;
while (enumerator.MoveNext())
{
i = (i + 1) % 3;
lastThreeElementIdxs[i] = enumerator.ElementIndex;
}
// The buffer index must be positive for a non-empty input
if (i >= 0)
{
// Extract indexes of the last 3 elements
// from the circular buffer
var i1 = lastThreeElementIdxs[(i + 1) % 3];
var i2 = lastThreeElementIdxs[(i + 2) % 3];
var i3 = lastThreeElementIdxs[i];
if (i1 >= 0 && i2 >= 0 && i3 >= 0 && // All 3 indexes must be initialized
i3 - i2 == 1 && i2 - i1 == 1 &&  // The 1 and 2 elements must be 1 char long
input[i1] == '|' &&              // The 1 element must be a pipe 
input[i2] == ' ')                // The 2 element must be a space
{
return input.Substring(0, i1);
}
}

return input;
}

最新更新