Làm cách nào để bạn có thể tách các ký tự không phải ASCII khỏi chuỗi? (trong C#)


180

Làm cách nào để bạn có thể tách các ký tự không phải ASCII khỏi chuỗi? (Trong C#)

+3

Mỗi câu trả lời của sinelaw [bên dưới] (http://stackoverflow.com/a/10036919/298754), nếu bạn muốn * thay thế * các ký tự không phải ASCII, ** xem [câu trả lời này] (http: // stackoverflow.com/a/10036907/562906) thay vào đó **. 10 dec. 132013-12-10 15:37:13

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

Đối với những người trong chúng ta RegEx'd thách thức, bạn sẽ nhớ viết ra bằng tiếng Anh đơn giản mô hình RegEx của bạn. Nói cách khác, "the^does this", vv ... 23 sep. 082008-09-23 22:45:15

+42

@Metro Smurf ^ là toán tử không. Nó nói với regex để tìm mọi thứ không khớp, thay vì mọi thứ phù hợp. \ u #### - \ u #### cho biết các ký tự nào phù hợp. \ U0000- \ u007F là tương đương với 255 ký tự đầu tiên trong utf-8 hoặc unicode, luôn là ký tự ascii. Vì vậy, bạn kết hợp mọi nhân vật không phải ascii (vì không phải) và thay thế mọi thứ phù hợp. 11 dec. 092009-12-11 21:11:26

+3

không 255, 127 .. xin lỗi bout rằng :) 11 dec. 092009-12-11 21:12:13

+33

Phạm vi cho các ký tự có thể in là 0020-007E, đối với những người tìm kiếm cụm từ thông dụng để thay thế các ký tự không thể in 17 feb. 142014-02-17 04:40:17

  0

Nếu bạn muốn xem bảng bộ ký tự ASCII: http: //www.asciitable.com/ 26 feb. 152015-02-26 15:06:05

  0

Phạm vi cho ** ASCII mở rộng ** là \ u0000- \ u00FF, cho những người tìm kiếm cụm từ thông dụng để thay thế các ký tự ASCII không mở rộng (ví dụ: đối với các ứng dụng có ngôn ngữ Tây Ban Nha, dấu phụ, v.v ...) 29 dec. 152015-12-29 21:30:50

+1

@GordonTucker \ u0000- \ u007F là sự tương đương với ** 127 ký tự đầu tiên ** trong utf-8 hoặc unicode và KHÔNG phải là 225 đầu tiên. Xem [table] (http://www.ascii-code.com/) 29 dec. 152015-12-29 21:33:56

+4

@full_prog_full Đó là lý do tại sao tôi trả lời bản thân mình khoảng một phút sau đó sửa bản thân mình để nói nó là 127 và không 255. :) 30 dec. 152015-12-30 21:46:35

  0

LED   Expo Thái Lan là tất cả các thiết lập cho phiên bản mới của mình trên   LED   công nghệ cách xóa mã ASCII trong C# 10 jan. 182018-01-10 11:46:58


96

Dưới đây là một giải pháp NET tinh khiết mà không sử dụng biểu thức thông thường:

 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) 
      ) 
     ); 

Nó có thể trông cồng kềnh, nhưng nó phải là trực quan. Nó sử dụng mã hóa .NET ASCII để chuyển đổi một chuỗi. UTF8 được sử dụng trong quá trình chuyển đổi vì nó có thể đại diện cho bất kỳ ký tự gốc nào. Nó sử dụng một EncoderReplacementFallback để chuyển đổi bất kỳ ký tự không phải ASCII nào thành một chuỗi rỗng.

+3

Hoàn hảo! Tôi đang sử dụng này để làm sạch một chuỗi trước khi lưu nó vào một tài liệu RTF. Rất nhiều đánh giá cao. Dễ hiểu hơn nhiều so với phiên bản Regex. 06 oct. 092009-10-06 16:48:26

+18

Bạn thực sự thấy dễ hiểu hơn không? Với tôi, tất cả những thứ không thực sự có liên quan (fallbacks, conversion to bytes etc) đều thu hút sự chú ý từ những gì thực sự xảy ra. 11 oct. 092009-10-11 15:28:54

  0

đã yêu thích ví dụ đó! 16 mar. 112011-03-16 11:03:38

+18

Đó là loại giống như nói rằng tua vít quá khó hiểu vì vậy tôi sẽ chỉ sử dụng một cái búa để thay thế. 03 aug. 112011-08-03 22:05:12

+7

@ Brandon, thực ra, kỹ thuật này không làm tốt công việc hơn các kỹ thuật khác. Vì vậy, tương tự sẽ được sử dụng một tua vít cũ cũ thay vì một iScrewDriver Deluxe 2000. :) 04 aug. 112011-08-04 07:46:09

  0

@ bzim Nó giống như sử dụng một cái búa trên một ốc vít :) OK không. Vì vậy, nó giống như sử dụng trục khuỷu của động cơ xe hơi của bạn để lái một ốc vít. Chúng tôi đi. 22 aug. 112011-08-22 17:10:45

  0

Làm thế nào chậm là điều này so với regex? Regex khá nhanh. 23 may. 132013-05-23 21:09:24

  0

@InsidiousForce, có thể phụ thuộc vào cụm từ thông dụng bạn sử dụng. Tại sao bạn không nhận một trong các biểu thức từ một trong những câu trả lời cho câu hỏi này và đánh giá nó? :) 27 may. 132013-05-27 08:36:34

+9

Một lợi thế là tôi có thể dễ dàng thay thế ASCII bằng ISO 8859-1 hoặc mã hóa khác :) 04 jul. 132013-07-04 03:34:35

  0

Chúng tôi có một Foxpro DB mà hệ thống của chúng tôi sử dụng, bị hỏng trong một giờ làm việc. Kể từ khi chức năng này được chạy trên hầu như mọi lĩnh vực của mỗi hàng tôi đã tò mò muốn biết sự khác biệt hiệu suất và nếu có bất cứ điều gì tốt hơn so với regexp đồng bằng. Đối với 1.000 chuỗi unicode được tạo ngẫu nhiên, thời gian chạy là 'Regexp: Trung bình: 3 ~ 4ms, Tối đa: 4ms' và' Chuyển đổi mã hóa: Trung bình: 4 ~ 5ms, Tối đa: 7ms' (không bao gồm tạo chuỗi, ngoài hẹn giờ) 16 jul. 132013-07-16 11:46:05

  0

@ syserr0r Thú vị. Kỹ thuật này có thể được tối ưu hóa, tùy thuộc vào thời gian. Ví dụ: 2 trường hợp dự phòng có thể được sử dụng lại. 05 aug. 132013-08-05 12:20:18

  0

Tôi đang tìm điều này nhanh hơn regex trên các chuỗi nhỏ hơn (chúng gần như ngay cả trên chuỗi ký tự 1000) và chậm hơn trên các chuỗi lớn hơn 02 oct. 142014-10-02 15:17:48

  0

Tự hỏi liệu tôi có thể sử dụng cách này để thay thế các ký tự không phải ascii bằng ký tự thay thế hay không. ví dụ: 'á' sẽ được thay thế bằng' a'. Điều này có thể không? 28 dec. 152015-12-28 12:42:01

  0

@RageCompex EncoderReplacementFallback không được thiết kế để chuyển đổi. Nhưng những gì bạn muốn có thể đạt được bằng cách sử dụng các API .NET để chuẩn hóa Unicode và Canonicalization. 30 dec. 152015-12-30 11:19:33


8

Lấy cảm hứng từ philcruz's Regular Expression solution, tôi đã thực hiện một giải pháp LINQ tinh khiết

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(); 
    } 

Đây là mã chưa được kiểm tra.

+1

Đối với những người không nắm bắt nó, đây là một giải pháp dựa trên C# 4.0 LINQ. :) 28 jan. 102010-01-28 20:49:59

+6

Thay vì phương thức ToText() riêng biệt, cách thay thế dòng 3 của PureAscii() bằng: trả về chuỗi mới (source.Select (c => c <min? Nil: c> max? Nil: c) .ToArray()); 10 nov. 112011-11-10 05:51:56

  0

Hoặc có lẽ ToText là: return (chuỗi mới (nguồn)) ToArray() - tùy thuộc vào những gì hoạt động tốt nhất. Nó vẫn là tốt đẹp để có ToText như một phương pháp mở rộng - thông thạo/đường ống phong cách. :-) 15 jan. 162016-01-15 10:14:21

  0

Mã đó thay thế các ký tự không phải ASCII bằng dấu cách. Để tách chúng ra, thay đổi Select to Where: 'return new string (source.Where (c => c> = min && c <= max) .ToArray());' 17 may. 172017-05-17 20:53:52

  0

@Foozinator Mã đó cho phép bạn chỉ định ký tự nào để thay thế các ký tự không phải ASCII bằng. Theo mặc định nó sử dụng một không gian, nhưng nếu nó được gọi là .PureASCII (Char.MinValue), nó sẽ thay thế tất cả các phi ASCII bằng '\ 0' - mà vẫn không chính xác tước chúng, nhưng kết quả tương tự. 29 nov. 172017-11-29 16:42:41


13

Nếu bạn muốn không tước, nhưng để thực sự chuyển đổi Latin có dấu để các ký tự không dấu, hãy nhìn vào câu hỏi này: How do I translate 8bit characters into 7bit characters? (i.e. Ü to U)

  0

Tôi thậm chí không nhận ra điều này là có thể, nhưng đó là một giải pháp tốt hơn cho tôi. Tôi sẽ thêm liên kết này vào nhận xét về câu hỏi để giúp mọi người tìm thấy dễ dàng hơn. Cảm ơn! 10 dec. 132013-12-10 15:36:16


1

tôi đã sử dụng biểu thức regex này:

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

Điều này cũng loại bỏ dấu chấm câu, chỉ trong trường hợp đó không phải là điều ai đó muốn. 18 jul. 122012-07-18 08:43:26


4

tôi thấy phạm vi thay đổi nhỏ sau đây hữu ích cho việc phân tích cú pháp các khối bình luận trong cơ sở dữ liệu, điều này có nghĩa là bạn sẽ không phải đối mặt với tab và thoát khỏi các ký tự khiến trường CSV trở nên khó chịu.

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

Nếu bạn muốn tránh ký tự đặc biệt khác hoặc dấu chấm câu đặc biệt kiểm tra the ascii table

+1

Trong trường hợp bất kỳ ai không nhận thấy các nhận xét khác, các ký tự có thể in thực sự là @ "[^ \ u0020- \ u007E]". Đây là một liên kết để xem bảng nếu bạn tò mò: http://www.asciitable.com/ 26 feb. 152015-02-26 15:03:47


6

không cần regex. chỉ cần sử dụng mã hóa ...

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

+1 câu trả lời tuyệt vời và đơn giản nhất từ ​​những người được liệt kê ở trên ... 25 aug. 132013-08-25 09:50:07

+5

Điều này không có tác dụng. Điều này không loại bỏ các ký tự unicode, nó thay thế chúng bằng? tính cách. 27 feb. 142014-02-27 16:56:11

+1

@David là đúng. Ít nhất tôi nhận được '???? nacho ?? 'khi tôi cố gắng:' た ま ね こ nacho な ち' trong mono 3.4 06 aug. 142014-08-06 02:38:08

  0

Bạn có thể khởi tạo lớp mã hóa của riêng bạn thay vì thay thế các ký tự nó loại bỏ chúng. Xem phương thức GetEncoding: https://msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx 01 apr. 162016-04-01 13:52:47


25

Tôi tin MonsCamus nghĩa:

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

IMHO Câu trả lời này tốt hơn câu trả lời được chấp nhận bởi vì nó loại bỏ các ký tự điều khiển. 25 sep. 172017-09-25 14:30:53

  0

LED &#160; Expo Thái Lan được thiết lập cho phiên bản mới của mình trên &#160; Công nghệ LED &#160; cách xóa mã ASCII trong C# 10 jan. 182018-01-10 11:46:39


2

Đây không phải là tối ưu hiệu suất-khôn ngoan, nhưng một cách tiếp cận LINQ khá thẳng về phía trước:

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

Các Nhược điểm là tất cả các ký tự "còn sống sót" trước tiên được đưa vào một mảng kiểu char[], sau đó được bỏ đi sau khi hàm tạo string không còn sử dụng nó nữa.


2

Tôi đến đây tìm kiếm giải pháp cho các ký tự ascii mở rộng, nhưng không thể tìm thấy nó. Tôi tìm thấy gần nhất là bzlm's solution. Nhưng điều đó chỉ hoạt động với mã ASCII tối đa 127 (rõ ràng là bạn có thể thay thế kiểu mã hóa trong mã của mình, nhưng tôi nghĩ nó có một chút phức tạp để hiểu. Do đó, việc chia sẻ phiên bản này). Dưới đây là một giải pháp mà làm việc cho extended ASCII codes i.e. upto 255ISO 8859-1

Nó tìm và dải ra các ký tự không ascii (lớn hơn 255)

Dim str1 as String= "â, ??î or ôu� n☁i✑++$-♓!‼⁉4⃣od;/⏬'®;☕:☝)///[email protected]#" 

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;/';:)///[email protected]#$%^yz: 

Dưới đây là một working fiddle for the code

Thay thế mã hóa theo yêu cầu , phần còn lại sẽ vẫn giữ nguyên.


0

Tôi sử dụng cụm từ thông dụng này để lọc ra các ký tự không hợp lệ trong tên tệp.

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

Đó phải là tất cả ký tự được phép đối với tên tệp.

  0

Không. Xem [Path.GetInvalidPathChars] (https://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars (v = vs.110) .aspx) và [Path.GetInvalidFileNameChars] (https://msdn.microsoft.com/en-us/library/system.io.path.getinvalidfilenamechars(v=vs.110).aspx). Vì vậy, có hàng chục ngàn ký tự hợp lệ. 10 jun. 172017-06-10 00:04:42

  0

Bạn nói đúng, Tom. Tôi đã thực sự nghĩ về những cái chung, nhưng tôi đã bỏ dấu ngoặc đơn và dấu ngoặc nhọn cũng như tất cả những thứ này - ^% $ # @! & + =. 12 jun. 172017-06-12 20:02:35