คุณจะตัดอักขระที่ไม่ใช่ ASCII ออกจากสตริงได้อย่างไร (ใน C #)


227

คุณจะตัดอักขระที่ไม่ใช่ ASCII ออกจากสตริงได้อย่างไร (ใน C #)


4
คำตอบต่อ sinelaw ของด้านล่างถ้าคุณต้องการที่จะแทนแทนที่อักขระที่ไม่ใช่ ASCII, ดูคำตอบนี้แทน
Bobson

คำตอบ:


414
string s = "søme string";
s = Regex.Replace(s, @"[^\u0000-\u007F]+", string.Empty);

19
สำหรับพวกเรา RegEx ขอท้าให้คุณช่วยเขียนภาษาอังกฤษของคุณในรูปแบบ RegEx กล่าวอีกนัยหนึ่ง "^ ทำสิ่งนี้" ฯลฯ ...
Smurf เมโทร

47
@Metro Smurf the ^ ไม่ใช่ตัวดำเนินการ มันบอก Regex ให้ค้นหาทุกสิ่งที่ไม่ตรงกันแทนที่จะเป็นทุกอย่างที่ตรงกัน \ u #### - \ u #### บอกว่าอักขระตัวใดตรงกัน \ u0000- \ u007F คือความเท่าเทียมของอักขระ 255 ตัวแรกใน utf-8 หรือ unicode ซึ่งเป็นอักขระ ASCII เสมอ ดังนั้นคุณจึงจับคู่อักขระที่ไม่ใช่ ASCII ทุกตัว (เพราะไม่ใช่) และทำการแทนที่ทุกอย่างที่ตรงกัน
Gordon Tucker

41
ช่วงสำหรับอักขระที่พิมพ์ได้คือ 0020-007E สำหรับผู้ที่มองหานิพจน์ทั่วไปเพื่อแทนที่อักขระที่ไม่สามารถพิมพ์ได้
Mubashar

1
@GordonTucker \ u0000- \ u007F นั้นเทียบเท่ากับอักขระ 127 ตัวแรกใน utf-8 หรือ unicode และไม่ใช่ 225 ตัวแรกดูตาราง
full_prog_full

4
@full_prog_full ซึ่งเป็นเหตุผลที่ผมตอบกับตัวเองประมาณนาทีต่อมาแก้ไขตัวเองที่จะบอกว่ามันเป็น 127 และ 255 ไม่ได้ :)
กอร์ดอนทักเกอร์

125

นี่คือโซลูชัน. NET บริสุทธิ์ที่ไม่ใช้นิพจน์ทั่วไป

string inputString = "Räksmörgås";
string asAscii = Encoding.ASCII.GetString(
    Encoding.Convert(
        Encoding.UTF8,
        Encoding.GetEncoding(
            Encoding.ASCII.EncodingName,
            new EncoderReplacementFallback(string.Empty),
            new DecoderExceptionFallback()
            ),
        Encoding.UTF8.GetBytes(inputString)
    )
);

มันอาจดูยุ่งยาก แต่ควรใช้งานง่าย มันใช้การเข้ารหัส. NET ASCII เพื่อแปลงสตริง UTF8 ถูกนำมาใช้ในระหว่างการแปลงเพราะมันสามารถเป็นตัวแทนของตัวละครเดิมใด ๆ มันใช้ EncoderReplacementFallback เพื่อแปลงอักขระที่ไม่ใช่ ASCII ให้เป็นสตริงว่าง


5
ที่สมบูรณ์แบบ! ฉันกำลังใช้สิ่งนี้เพื่อล้างสตริงก่อนบันทึกลงในเอกสาร RTF ชื่นชมมาก เข้าใจง่ายกว่ารุ่น Regex มาก
นาธาน Prather

21
คุณเข้าใจหรือไม่ สำหรับฉันทุกสิ่งที่ไม่เกี่ยวข้อง (ทางเลือกการแปลงเป็นไบต์ ฯลฯ ) กำลังดึงความสนใจออกไปจากสิ่งที่เกิดขึ้นจริง
bzlm

21
มันเหมือนกับว่าไขควงมีความสับสนเกินไปดังนั้นฉันจะใช้ค้อนแทน
แบรนดอน

8
@Brandon ที่จริงแล้วเทคนิคนี้ไม่ได้ทำงานได้ดีกว่าเทคนิคอื่น ๆ ดังนั้นการเปรียบเทียบจะใช้ไขควง olde ธรรมดาแทนที่จะเป็น iScrewDriver Deluxe 2000 ที่
หรูหรา

10
ข้อดีอย่างหนึ่งคือว่าผมสามารถแทนที่ ASCII มาตรฐาน ISO 8859-1 หรือการเข้ารหัสอื่น :)
อากิระยามาโมโตะ

38

ฉันเชื่อว่า MonsCamus หมายถึง:

parsememo = Regex.Replace(parsememo, @"[^\u0020-\u007E]", string.Empty);

1
IMHO คำตอบนี้ดีกว่าคำตอบที่ยอมรับได้เพราะจะตัดอักขระควบคุมออก
Dean2690

15

หากคุณไม่ต้องการถอดออก แต่เพื่อแปลงลาตินที่เน้นเสียงเป็นตัวอักษรที่ไม่เน้นเสียงให้ดูที่คำถามนี้: ฉันจะแปลอักขระ 8 บิตเป็นอักขระ 7 บิตได้อย่างไร (เช่นÜถึง U)


ฉันไม่ได้ตระหนักว่านี่เป็นไปได้ แต่มันเป็นทางออกที่ดีกว่าสำหรับฉัน ฉันจะเพิ่มลิงค์นี้เพื่อแสดงความคิดเห็นในคำถามเพื่อให้คนอื่นค้นพบได้ง่ายขึ้น ขอบคุณ!
Bobson

11

แรงบันดาลใจจากโซลูชัน Expression ปกติของ philcruzฉันได้สร้างโซลูชัน LINQ อย่างแท้จริงแล้ว

public static string PureAscii(this string source, char nil = ' ')
{
    var min = '\u0000';
    var max = '\u007F';
    return source.Select(c => c < min ? nil : c > max ? nil : c).ToText();
}

public static string ToText(this IEnumerable<char> source)
{
    var buffer = new StringBuilder();
    foreach (var c in source)
        buffer.Append(c);
    return buffer.ToString();
}

นี่คือรหัสที่ยังไม่ทดลอง


1
สำหรับผู้ที่ไม่เข้าใจนี่เป็นโซลูชั่นที่ใช้ CQ 4.0 LINQ :)

7
แทนที่จะใช้วิธี ToText () แยกวิธีเปลี่ยนบรรทัดที่ 3 ของ PureAscii () ด้วย: คืนค่าสตริงใหม่ (source.Select (c => c <min? nil: c> max? nil: c) .ToArray () ;
agentnega

หรือบางที ToText as: return (new string (source)) ToArray () - ขึ้นอยู่กับสิ่งที่ทำงานได้ดีที่สุด ก็ยังดีที่มี ToText เป็นวิธีการขยาย - สไตล์คล่องแคล่ว / ท่อ :-)
Bent Rasmussen

รหัสนั้นจะแทนที่อักขระที่ไม่ใช่ ASCII ด้วยช่องว่าง หากต้องการตัดออกให้เปลี่ยนเลือกเป็นตำแหน่ง:return new string( source.Where( c => c >= min && c <= max ).ToArray() );
Foozinator

@Foozinator รหัสนั้นอนุญาตให้คุณระบุอักขระที่จะแทนที่อักขระที่ไม่ใช่ ASCII ด้วย โดยค่าเริ่มต้นจะใช้ช่องว่าง แต่ถ้าเรียกว่า. PUREASCII (Char.MinValue) มันจะแทนที่ไม่ใช่ ASCII ทั้งหมดด้วย '\ 0' - ซึ่งยังคงไม่ลอกพวกเขา แต่ผลลัพธ์ที่คล้ายกัน
Ulfius

5

ไม่จำเป็นต้องใช้ regex เพียงใช้การเข้ารหัส ...

sOutput = System.Text.Encoding.ASCII.GetString(System.Text.Encoding.ASCII.GetBytes(sInput));

5
สิ่งนี้ใช้ไม่ได้ สิ่งนี้ไม่ได้ตัดอักขระ Unicode มันจะแทนที่ด้วย? ตัวละคร
David

1
@ David ถูกต้อง อย่างน้อยฉันได้????nacho??เมื่อฉันลอง: たまねこnachoなちในขาวดำ 3.4
nacho4d

1
คุณสามารถยกระดับคลาสการเข้ารหัสของคุณเองแทนการแทนที่ตัวอักษรมันจะลบออก ดูวิธี GetEncoding: msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx
kkara

4

ฉันพบว่าช่วงที่เปลี่ยนแปลงเล็กน้อยต่อไปนี้มีประโยชน์สำหรับการแยกบล็อกความคิดเห็นออกจากฐานข้อมูลซึ่งหมายความว่าคุณไม่ต้องโต้แย้งกับแท็บและอักขระเลี่ยงซึ่งจะทำให้ฟิลด์ CSV กลายเป็นอารมณ์เสีย

parsememo = Regex.Replace(parsememo, @"[^\u001F-\u007F]", string.Empty);

หากคุณต้องการหลีกเลี่ยงอักขระพิเศษอื่น ๆ หรือเครื่องหมายวรรคตอนเฉพาะให้ตรวจสอบตาราง ascii


1
ในกรณีที่ไม่มีใครสังเกตเห็นความคิดเห็นอื่นอักขระที่พิมพ์ได้จริง ๆ คือ @ "[^ \ u0020- \ u007E]" นี่คือลิงค์สำหรับดูตารางหากคุณสงสัย: asciitable.com
scradam

3

ฉันมาที่นี่เพื่อค้นหาวิธีแก้ปัญหาสำหรับอักขระ ascii ที่ขยายเพิ่ม ผมพบว่าที่ใกล้ที่สุดคือวิธีการแก้ปัญหาของ bzlm แต่ใช้งานได้กับรหัส ASCII ไม่เกิน 127 เท่านั้น (เห็นได้ชัดว่าคุณสามารถแทนที่ประเภทการเข้ารหัสในรหัสของเขาได้ แต่ฉันคิดว่ามันค่อนข้างซับซ้อนที่จะเข้าใจดังนั้นแบ่งปันเวอร์ชันนี้) ต่อไปนี้เป็นโซลูชันที่ใช้งานได้กับรหัส ASCII เพิ่มเติมเช่นสูงสุด 255ซึ่งเป็นISO 8859-1

ค้นหาและตัดส่วนอักขระที่ไม่ใช่ ASCII (มากกว่า 255)

Dim str1 as String= "â, ??î or ôu🕧� n☁i✑💴++$-💯♓!🇪🚑🌚‼⁉4⃣od;/⏬'®;😁☕😁:☝)😁😁///😍1!@#"

Dim extendedAscii As Encoding = Encoding.GetEncoding("ISO-8859-1", 
                                                New EncoderReplacementFallback(String.empty),
                                                New DecoderReplacementFallback())

Dim extendedAsciiBytes() As Byte = extendedAscii.GetBytes(str1)

Dim str2 As String = extendedAscii.GetString(extendedAsciiBytes)

console.WriteLine(str2)
'Output : â, ??î or ôu ni++$-!‼⁉4od;/';:)///1!@#$%^yz:

นี่คือซอที่ใช้งานได้สำหรับโค้ด

แทนที่การเข้ารหัสตามความต้องการส่วนที่เหลือควรอยู่ในสภาพเดิม


2
มีเพียงหนึ่งเดียวเท่านั้นที่ทำงานเพื่อลบเฉพาะΩจากสตริงนี้ "Ω c çã" ขอบคุณมาก!
Rafael Araújo

2

นี่ไม่ใช่ประสิทธิภาพที่ดีที่สุด แต่เป็นวิธีที่ตรงไปตรงมา Linq:

string strippedString = new string(
    yourString.Where(c => c <= sbyte.MaxValue).ToArray()
    );

ข้อเสียคือตัวละคร "ที่รอดตาย" ทั้งหมดจะถูกใส่ลงในอาร์เรย์ประเภทแรกchar[]ซึ่งจะถูกโยนทิ้งไปหลังจากตัวstringสร้างไม่ได้ใช้อีกต่อไป


1

ฉันใช้นิพจน์ regex นี้:

    string s = "søme string";
    Regex regex = new Regex(@"[^a-zA-Z0-9\s]", (RegexOptions)0);
    return regex.Replace(s, "");

16
สิ่งนี้จะลบเครื่องหมายวรรคตอนเช่นกันในกรณีที่ไม่ใช่สิ่งที่ใครบางคนต้องการ
Drew Noakes

1

ฉันใช้นิพจน์ทั่วไปนี้เพื่อกรองอักขระที่ไม่ดีในชื่อไฟล์

Regex.Replace(directory, "[^a-zA-Z0-9\\:_\- ]", "")

นั่นควรเป็นอักขระทั้งหมดที่อนุญาตให้ใช้ชื่อไฟล์


1
Nope ดูPath.GetInvalidPathCharsและPath.GetInvalidFileNameChars ดังนั้นจึงมีอักขระที่ใช้ได้หลายหมื่นตัว
Tom Blodget

คุณถูกต้องทอม จริง ๆ แล้วฉันคิดเกี่ยวกับคนทั่วไป แต่ฉันไม่ได้ใช้วงเล็บและวงเล็บปีกการวมถึงสิ่งเหล่านี้ - ^% $ # @! & + =
user890332
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.