簡體   English   中英

從字符串中刪除隱藏字符

[英]Removing hidden characters from within strings

我的問題:

我有一個 .NET 應用程序,它通過 email 發送時事通訊。當在 outlook 中查看時事通訊時,outlook 顯示一個問號代替它無法識別的隱藏字符。 這些隱藏字符來自最終用戶,他們將組成時事通訊的 html 復制並粘貼到表單中並提交。 c# trim() 會刪除這些隱藏的字符(如果它們出現在字符串的末尾或開頭)。 當在 gmail 中查看時事通訊時,gmail 會很好地忽略它們。 在 word 文檔中粘貼這些隱藏字符時,我打開“顯示段落標記和隱藏符號”選項,這些符號顯示為一個更大矩形內的一個矩形。 此外,構成時事通訊的文本可以使用任何語言,因此必須接受 Unicode 個字符。 我試過循環遍歷字符串來檢測字符,但循環無法識別它並通過它。 還要求最終用戶在提交之前先將 html 粘貼到記事本中,這是不可能的。

我的問題:
如何使用 C# 檢測並消除這些隱藏字符?

您可以使用以下內容從輸入字符串中刪除所有控制字符:

string input; // this is your input string
string output = new string(input.Where(c => !char.IsControl(c)).ToArray());

這是IsControl()方法的文檔

或者,如果您只想保留字母和數字,也可以使用IsLetterIsDigit函數:

string output = new string(input.Where(c => char.IsLetter(c) || char.IsDigit(c)).ToArray());

我通常使用這個正則表達式來替換所有不可打印的字符。

順便說一句,大多數人認為制表符、換行符和回車符是不可打印的字符,但對我來說不是。

所以這里是表達式:

string output = Regex.Replace(input, @"[^\u0009\u000A\u000D\u0020-\u007E]", "*");
  • ^表示是否屬於以下任何一種情況:
  • \ 是制表符
  • \ 是換行
  • \ 是回車
  • \ -\~表示從空格到~所有內容——即 ASCII 中的所有內容。

如果要進行更改,請參閱ASCII 表 請記住,它會去除每個非 ASCII 字符。

要進行上面的測試,您可以像這樣自己創建一個字符串:

    string input = string.Empty;

    for (int i = 0; i < 255; i++)
    {
        input += (char)(i);
    }

最適合我的是:

string result = new string(value.Where(c =>  char.IsLetterOrDigit(c) || (c >= ' ' && c <= byte.MaxValue)).ToArray());

在我確保字符是任何字母或數字的地方,這樣我就不會忽略任何非英文字母,或者如果它不是一個字母,我會檢查它是否是一個大於或等於 Space 的 ascii 字符以確保我忽略了一些控制字符,這確保我不會忽略標點符號。

有些人建議使用 IsControl 檢查字符是否不可打印,但例如忽略從左到右標記。

new string(input.Where(c => !char.IsControl(c)).ToArray());

IsControl 遺漏了一些控制字符,如從左到右標記 (LRM)(在執行復制粘貼時通常隱藏在字符串中的字符)。 如果您確定您的字符串只有數字和數字,那么您可以使用 IsLetterOrDigit

new string(input.Where(c => char.IsLetterOrDigit(c)).ToArray())

如果你的字符串有特殊字符,那么

new string(input.Where(c => c < 128).ToArray())

你可以這樣做:

var hChars = new char[] {...};
var result = new string(yourString.Where(c => !hChars.Contains(c)).ToArray());

如果你知道這些字符是什么,你可以使用string.Replace

newString = oldString.Replace("?", "");

在哪里“?” 表示要刪除的字符。

這種方法的缺點是,如果要刪除多個字符,則需要重復進行此調用。

已經有一段時間了,但尚未得到回答。

如何在發送代碼中包含HMTL內容? 如果您從文件中讀取它,請檢查文件編碼。 如果您使用帶簽名的UTF-8(名稱在編輯器之間略有不同),這可能會導致郵件開頭的奇怪字符。

我使用這個快速而骯臟的 oneliner 來清除損壞的 Windows 10 計算器應用程序留下的 LTR/RTL 標記中的一些輸入。 這可能與完美相去甚遠,但足以快速修復:

string cleaned = new string(input.Where(c => !char.IsControl(c) && (char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsSeparator(c) || char.IsSymbol(c) || char.IsWhiteSpace(c))).ToArray());

TLDR 答案

使用這個正則表達式...

\P{Cc}\P{Cn}\P{Cs}

像這樣...

var regex = new Regex(@"![\P{Cc}\P{Cn}\P{Cs}]");

TLDR 解釋

  • \\P{Cc}匹配控制字符。
  • \\P{Cn}匹配未分配的字符。
  • \\P{Cs}匹配 UTF-8 無效字符。

工作演示

在這個演示中,我使用這個正則表達式來搜索字符串"Hello, World!" . 最后那個奇怪的字符是(char)4 — 這是END TRANSMISSION的字符。

using System;
using System.Text.RegularExpressions;

public class Test {
    public static void Main() {
        var regex = new Regex(@"![\P{Cc}\P{Cn}\P{Cs}]");
        var matches = regex.Matches("Hello, World!" + (char)4);
        Console.WriteLine("Results: " + matches.Count);
        foreach (Match match in matches) {
            Console.WriteLine("Result: " + match);
        }
    }
}

IDEOne.com 上的完整工作演示

上述代碼的輸出:

Results: 1
Result: !

備擇方案

  • \\P{C} :只匹配可見字符。 不匹配任何不可見字符。
  • \\P{Cc} :只匹配非控制字符。 不匹配任何控制字符。
  • \\P{Cc}\\P{Cn} :僅匹配已分配的非控制字符。 不匹配任何控制或未分配的字符。
  • \\P{Cc}\\P{Cn}\\P{Cs} :僅匹配已分配且 UTF-8 有效的非控制字符。 不匹配任何控制字符、未分配字符或 UTF-8 無效字符。
  • \\P{Cc}\\P{Cn}\\P{Cs}\\P{Cf} :僅匹配已分配且 UTF-8 有效的非控制、非格式化字符。 不匹配任何控制、未分配、格式或 UTF-8 無效字符。

來源和解釋

查看可用於在正則表達式中進行測試的Unicode 字符屬性 您應該能夠在Microsoft .NETJavaScriptPythonJavaPHPRubyPerlGolang甚至Adobe 中使用這些正則表達式。 了解 Unicode 字符類是非常可遷移的知識,所以我推薦使用它!

我遇到 AWS S3 SDK 錯誤“目標資源路徑 [名稱 -3.30.2022 -15.27.00.pdf] 具有雙向字符,System.Uri 不支持這些字符,因此 .NET SDK 無法處理”

我實例中的文件名在點之間包含 Unicode 個字符“LEFT-TO-RIGHT MARK”(U+200E)。 這些在 html 或 Notepad++ 中不可見。 當文本被粘貼到 Visual Studio 2019 編輯器中時,unicode 文本可見,我能夠解決這個問題。

U+200E 從左到右標記

通過使用以下腳本替換文件名中的所有控制字符和其他不可打印字符,問題得以解決。

var input = Regex.Replace(s, @"\p{C}+", string.Empty);

來源: https://stackoverflow.com/a/40568888/1165173

string output = new string(input.Where(c => !char.IsControl(c)).ToArray());

這肯定會解決問題。 我在一個字符串中有一個不可打印的替代字符(ASCII 26),這導致我的應用程序中斷,這行代碼刪除了這些字符

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM