2008-09-26 52 views
21

Tôi có luồng dữ liệu có thể chứa \ r, \ n, \ r \ n, \ n \ r hoặc bất kỳ kết hợp nào của chúng. Có cách nào đơn giản để bình thường hóa dữ liệu để làm cho tất cả chúng đơn giản trở thành cặp \ r \ n để làm cho màn hình hiển thị nhất quán hơn?Chuẩn hóa dòng mới trong C#

Vì vậy, cái gì đó sẽ mang lại loại bảng dịch:

\r  --> \r\n 
\n  --> \r\n 
\n\n --> \r\n\r\n 
\n\r --> \r\n 
\r\n --> \r\n 
\r\n\n --> \r\n\r\n 
+2

Chờ, vì vậy bạn muốn \ n \ r ánh xạ tới \ r \ n? Đó không phải là bình thường hóa. Không có nền tảng phổ biến nào sử dụng \ n \ r như một dòng kết thúc. –

+2

Không nói nó là một nền tảng bình thường, phải không? Tôi đã nhìn thấy dữ liệu (từ mã VB cụ thể) mã có nó theo cách đó, và tôi cần phải tài khoản cho nó. Xin lỗi nếu điều đó không đáp ứng định nghĩa "chuẩn hóa" nghiêm ngặt nhưng chắc chắn đáp ứng định nghĩa của dữ liệu tôi cần xử lý, đó là điểm – ctacke

Trả lời

29

Tôi tin rằng điều này sẽ làm những gì bạn cần:

using System.Text.RegularExpressions; 
// ... 
string normalized = Regex.Replace(originalString, @"\r\n|\n\r|\n|\r", "\r\n"); 

Tôi không chắc chắn 100% về cú pháp chính xác, và tôi không có một trình biên dịch Net tiện để kiểm tra. Tôi đã viết nó trong perl, và chuyển đổi nó thành (hy vọng chính xác) C#. Bí quyết thực sự duy nhất là khớp với "\ r \ n" và "\ n \ r" trước tiên.

Để áp dụng nó cho toàn bộ luồng, chỉ cần chạy trên các phần đầu vào. (Bạn có thể làm điều này với một wrapper dòng nếu bạn muốn.)


Các perl gốc:

$str =~ s/\r\n|\n\r|\n|\r/\r\n/g; 

Các kết quả xét nghiệm:

[bash$] ./test.pl 
\r -> \r\n 
\n -> \r\n 
\n\n -> \r\n\r\n 
\n\r -> \r\n 
\r\n -> \r\n 
\r\n\n -> \r\n\r\n 

Cập nhật: Bây giờ cải \ n \ r tới \ r \ n, mặc dù tôi sẽ không gọi đó là chuẩn hóa.

+0

Điều này không đáp ứng các yêu cầu của ví dụ trên trong bảng .. Nhìn vào regex tôi đã sửa đổi, bạn cần tính đến \ n \ n. –

+0

Đây là một đóng, nhưng \ n \ r chỉ cần trao đổi các phần tử thành một \ r \ n (xem đầu vào này từ mã của nhà phát triển VB) – ctacke

+0

Ok, đã thực hiện thay đổi đó. Tôi sẽ không xem xét việc bình thường hóa, nhưng thật dễ dàng để thêm vào regex. –

3

Một Regex sẽ giúp .. có thể làm một cái gì đó gần như thế này ..

(\ r \ n | \ n \ n | \ n \ r | \ r | \ n) thay thế bằng \ r \ n

Regex này tạo ra các kết quả này từ bảng được đăng (chỉ cần kiểm tra bên trái) để thay thế nên bình thường hóa.

\r => \r 
\n => \n 
\n\n => \n\n 
\n\r => \n\r 
\r\n => \r\n 
\r\n => \r\n 
\n => \n 
+0

Trừ khi nó đã có \ r \ n, thay thế sẽ mở rộng thành \ r \ n \ r \ n. Tương tự cho \ n \ r. Tôi tin rằng câu trả lời là trong ngôn ngữ phức tạp của regex, nhưng đó là một nghệ thuật đen với tôi. – ctacke

+0

CQ, điều đó không làm những gì anh ta yêu cầu. Một regex có thể làm việc, nhưng không phải như bạn đã đăng nó. –

+0

Đồng ý Tôi không có tài khoản hiện tại \ r \ n –

0

Bạn đang suy nghĩ quá phức tạp. Bỏ qua mọi \ r và biến mọi \ n thành \ r \ n.

Trong Pseudo-C#:

char[] chunk = new char[X]; 
StringBuffer output = new StringBuffer(); 

buffer.Read(chunk); 
foreach (char c in chunk) 
{ 
    switch (c) 
    { 
     case '\r' : break; // ignore 
     case '\n' : output.Append("\r\n"); 
     default : output.Append(c); 
    } 
} 

EDIT: \ r thôi thì không có line-terminator vì vậy tôi nghi ngờ bạn thực sự muốn mở rộng \ r để \ r \ n.

+0

Anh ấy muốn độc lập để biến thành \ r \ n. –

+0

Hm. Không thể tin rằng anh ấy thực sự muốn điều đó :) – VVS

+4

Máy Mac đã sử dụng CR cho các lần ngắt dòng lên tới MacOS 9. Đó là \ n \ r khiến tôi ngạc nhiên. –

3

Tôi với Jamie Zawinski trên RegEx:

"Một số người, khi phải đối mặt với một vấn đề, suy nghĩ" Tôi biết, tôi sẽ sử dụng biểu thức thông thường."Bây giờ họ có hai vấn đề"

Đối với những người trong chúng ta thích đọc:

  • Bước 1

    Replace \ r \ n bởi \ n

    Replace \ n \ r bằng \ n (nếu bạn thực sự muốn điều này, một số áp phích có vẻ như không nghĩ)

    Thay \ r by \ n

  • Bước 2 Thay thế \ n bằng Environment.NewLine hoặc \ r \ n hoặc bất kỳ thứ gì.

+5

Đây là một regex tầm thường. Tôi sẽ đồng ý với bạn nếu đó là phân tích HTML. – cchamberlain

1

Tôi đồng ý Regex là câu trả lời, tuy nhiên, những người khác không đề cập đến bộ tách dòng Unicode. Những người (và các biến thể của họ với \ n) nên được bao gồm.

+1

Bạn đã có giải pháp cho điều đó chưa? Nó sẽ hữu ích để biết. – Phil

0

Đồng hóa phá vỡ, do đó họ là tất cả \r\n

var normalisedString = 
      sourceString 
      .Replace("\r\n", "\n") 
      .Replace("\n\r", "\n") 
      .Replace("\r", "\n") 
      .Replace("\n", "\r\n"); 
0

Đây là câu trả lời cho câu hỏi này. Giải pháp đã cho thay thế một chuỗi bằng bảng dịch đã cho. Nó không sử dụng chức năng regex đắt tiền. Nó cũng không sử dụng nhiều chức năng thay thế mà mỗi cá nhân đã lặp qua dữ liệu với một số kiểm tra, v.v.

Vì vậy, tìm kiếm được thực hiện trực tiếp trong 1 cho vòng lặp. Đối với số lần công suất của mảng kết quả phải được tăng lên, một vòng lặp cũng được sử dụng trong hàm Array.Copy. Đó là tất cả các vòng lặp. Trong một số trường hợp, kích thước trang lớn hơn có thể hiệu quả hơn.

public static string NormalizeNewLine(this string val) 
{ 
    if (string.IsNullOrWhiteSpace(val)) 
     return val; 

    const int page = 6; 
    int a = page; 
    int j = 0; 
    int len = val.Length; 
    char[] res = new char[len]; 

    for (int i = 0; i < len; i++) 
    { 
     char ch = val[i]; 

     if (ch == '\r') 
     { 
      int ni = i + 1; 
      if (ni < len && val[ni] == '\n') 
      { 
       res[j++] = '\r'; 
       res[j++] = '\n'; 
       i++; 
      } 
      else 
      { 
       if (a == page) //ensure capacity 
       { 
        char[] nres = new char[res.Length + page]; 
        Array.Copy(res, 0, nres, 0, res.Length); 
        res = nres; 
        a = 0; 
       } 

       res[j++] = '\r'; 
       res[j++] = '\n'; 
       a++; 
      } 
     } 
     else if (ch == '\n') 
     { 
      int ni = i + 1; 
      if (ni < len && val[ni] == '\r') 
      { 
       res[j++] = '\r'; 
       res[j++] = '\n'; 
       i++; 
      } 
      else 
      { 
       if (a == page) //ensure capacity 
       { 
        char[] nres = new char[res.Length + page]; 
        Array.Copy(res, 0, nres, 0, res.Length); 
        res = nres; 
        a = 0; 
       } 

       res[j++] = '\r'; 
       res[j++] = '\n'; 
       a++; 
      } 
     } 
     else 
     { 
      res[j++] = ch; 
     } 
    } 

    return new string(res, 0, j); 
} 

Bảng dịch thực sự hấp dẫn tôi ngay cả khi '\ n \ r' không thực sự được sử dụng trên nền tảng cơ bản. Ai sẽ sử dụng hai loại ngắt dòng liên tiếp để chỉ ra 2 dấu ngắt dòng? Nếu bạn muốn biết điều đó, bạn cần phải xem trước khi biết \ n và \ r đều được sử dụng riêng trong cùng một tài liệu hay không.