2009-08-14 81 views
201

Làm thế nào là \r\n khác nhau? Tôi nghĩ rằng nó có một cái gì đó để làm với Unix vs Windows so với Mac, nhưng tôi không chắc chắn chính xác như thế nào họ đang khác nhau, và đó để tìm kiếm/phù hợp trong regexes.Sự khác biệt giữa r và n là gì?

+1

Điều này cần thẻ ngôn ngữ. Các ngôn ngữ khác nhau có cách diễn giải khác nhau của ''\ n''. –

Trả lời

314

Chúng là các ký tự khác nhau. \r là phương tiện chuyên chở và \n là nguồn cấp dữ liệu dòng.

Trên máy in "cũ", \r đã gửi đầu in trở lại đầu dòng và \n nâng cấp giấy lên một dòng. Do đó, cả hai đều cần thiết để bắt đầu in trên dòng tiếp theo.

Rõ ràng là hơi không liên quan, mặc dù tùy thuộc vào bảng điều khiển, bạn vẫn có thể sử dụng \r để di chuyển đến đầu dòng và ghi đè văn bản hiện tại.

Quan trọng hơn, Unix có xu hướng sử dụng \n làm dấu tách dòng; Windows có xu hướng sử dụng \r\n làm dấu tách dòng và máy Mac (tối đa OS 9) được sử dụng để sử dụng \r làm dấu tách dòng. (Mac OS X là Unix-y, vì vậy hãy sử dụng \n thay vào đó; có thể có một số tình huống tương thích trong đó \r được sử dụng thay thế.)

Để biết thêm thông tin, hãy xem Wikipedia newline article.

EDIT: Đây là ngôn ngữ nhạy cảm. Trong C# và Java, ví dụ, \nluôn luôn có nghĩa là Unicode U + 000A, được định nghĩa là nguồn cấp dữ liệu dòng. Trong C và C++ nước là hơi bùn, vì ý nghĩa là nền tảng cụ thể. Xem nhận xét để biết chi tiết.

+19

+1 dành cho người già. Đầu ra của thiết bị đầu cuối được sử dụng để điều khiển trực tiếp một thiết bị đầu cuối điện tử được tôn vinh (TTY của bạn trước các màn hình CRT lạ mắt). Do đó, chúng ta có được những hiện vật tuyệt vời của những người trong sự trở về vận chuyển và các nhân vật mới (cả hai đều có thể cần thiết, như Jon Skeet đã đề cập) và những thứ như \ a "chuông", \ b "backspace" (không bị nhầm lẫn với "xóa "), và tất cả các nhân vật điều khiển khác cần thiết để giao tiếp với một tty. – erjiang

+35

+1 khác dành cho người cũ. Bạn vẫn có thể nhấn Ctrl + G trên cửa sổ nhắc lệnh, nhấn enter và loa PC sẽ phát ra tiếng bíp. Điều đó còn sót lại từ thời cổ đại. –

+0

@Crappy Coding Guy thực sự? Trên Vista, nó chỉ nói "'' không được công nhận là một lệnh nội bộ hoặc bên ngoài" – Ponkadoodle

2

\ r là Vận chuyển trở lại; \ n là New Line (Line Feed) ... phụ thuộc vào hệ điều hành theo ý nghĩa của từng loại. Đọc này article để biết thêm về sự khác biệt giữa '\ n' và '\ r \ n' ... trong C.

4

Trong ngắn \ r có giá trị ASCII 13 (CR) và \ n có giá trị ASCII 10 (LF). Mac sử dụng CR làm dấu tách dòng (ít nhất, nó đã làm trước đó, tôi không chắc chắn cho các máy Mac hiện đại), * nix sử dụng LF và Windows sử dụng cả hai (CRLF).

+1

Hệ thống Mac OS X sử dụng LF theo mặc định (vì nó dựa trên BSD Unix). – dreamlax

3

Ngoài @ Jon Skeet câu trả lời:

Theo truyền thống Windows đã sử dụng \ r \ n, Unix \ n và Mac \ r, Mac tuy nhiên mới sử dụng \ n như họ unix dựa.

9
  • "\ r" => Return
  • "\ n" => Newline hay linefeed (ngữ nghĩa)

  • Unix dựa trên hệ thống sử dụng chỉ là một "\ n" để kết thúc một dòng bản văn.

  • Dos sử dụng "\ r \ n" để kết thúc dòng văn bản.
  • Một số máy khác chỉ sử dụng "\ r". (Commodore, Apple II, Mac OS trước khi OS X, vv ..)
78

Trong C và C++, \n là một khái niệm, \r là một nhân vật, và \r\n là (hầu như luôn luôn) một lỗi tính di động.

Hãy suy nghĩ về một kiểu chữ cũ.Đầu in được đặt trên một số dòng và trong một số cột. Khi bạn gửi một ký tự có thể in đến kiểu chữ, nó sẽ in ký tự ở vị trí hiện tại và di chuyển đầu đến cột tiếp theo. (Đây là khái niệm giống như máy đánh chữ, ngoại trừ việc máy đánh chữ thường di chuyển giấy liên quan đến đầu in.)

Khi bạn muốn kết thúc dòng hiện tại và bắt đầu dòng tiếp theo, bạn phải làm hai bước sau:

  1. di chuyển đầu in trở lại đầu dòng, sau đó
  2. di chuyển nó xuống dòng tiếp theo.

ASCII mã hóa những hành động như hai ký tự điều khiển riêng biệt:

  • \x0D (CR) di chuyển đầu in lại phần đầu của dòng. (Unicode mã hóa mã này thành U+000D CARRIAGE RETURN.)
  • \x0A (LF) di chuyển đầu in xuống dòng tiếp theo. (Unicode mã hóa số này là U+000A LINE FEED.)

Trong những ngày của máy in và máy in công nghệ, mọi người thực sự lợi dụng thực tế rằng đây là hai hoạt động riêng biệt. Bằng cách gửi một CR mà không theo sau nó bằng một LF, bạn có thể in trên dòng bạn đã in. Điều này cho phép các hiệu ứng như dấu trọng âm, loại in đậm và gạch dưới. Một số hệ thống được in nhiều lần để ngăn không cho mật khẩu hiển thị trong bản cứng. Trên các thiết bị đầu cuối CRT nối tiếp đầu tiên, CR là một trong những cách điều khiển vị trí con trỏ để cập nhật văn bản đã có trên màn hình.

Nhưng hầu hết thời gian, bạn thực sự chỉ muốn chuyển sang dòng tiếp theo. Thay vì yêu cầu cặp ký tự điều khiển, một số hệ thống chỉ cho phép một hoặc hai hệ thống khác. Ví dụ:

  • Biến thể Unix (bao gồm các phiên bản Mac hiện đại) chỉ sử dụng ký tự LF để biểu thị dòng mới.
  • Tệp cũ Macintosh (trước OSX) chỉ sử dụng ký tự CR để biểu thị dòng mới.
  • VMS, CP/M, DOS, Windows và nhiều giao thức mạng mạng vẫn mong đợi cả hai: CR LF.
  • Hệ thống cũ của IBM sử dụng EBCDIC được tiêu chuẩn hóa trên NL - một ký tự không còn tồn tại trong bộ ký tự ASCII. Trong Unicode, NL là U+0085 NEXT LINE, nhưng giá trị EBCDIC thực tế là 0x15.

Tại sao các hệ thống khác nhau lại chọn các phương pháp khác nhau? Đơn giản vì không có tiêu chuẩn phổ quát. Nơi bàn phím của bạn có thể nói "Enter", bàn phím cũ hơn được sử dụng để nói "Return", viết tắt của Carriage Return. Trong thực tế, trên một thiết bị đầu cuối nối tiếp, nhấn Return thực sự gửi ký tự CR. Nếu bạn đang viết một trình soạn thảo văn bản, nó sẽ là hấp dẫn để chỉ sử dụng nhân vật đó khi nó đến từ các thiết bị đầu cuối. Có lẽ đó là lý do tại sao các máy Mac cũ chỉ sử dụng CR.

Bây giờ chúng tôi có standards, có nhiều hơn cách để trình bày ngắt dòng.Mặc dù rất hiếm trong tự nhiên, Unicode có nhân vật mới như:

  • U+2028 LINE SEPARATOR
  • U+2029 PARAGRAPH SEPARATOR

Ngay cả trước khi Unicode đến cùng, các lập trình viên muốn cách đơn giản để đại diện cho một số các mã kiểm soát hữu ích nhất mà không lo lắng về bộ ký tự cơ bản. C có một số trình tự thoát cho đại diện cho mã kiểm soát:

  • \a (cho cảnh báo) mà nhẫn chuông teletype hoặc làm cho tiếng bíp terminal
  • \f (đối với thức ăn chăn nuôi theo mẫu) trong đó di chuyển đến đầu trang tiếp theo
  • \t (ví tab) trong đó di chuyển đầu in đến vị trí tab ngang tiếp theo

(danh sách này là cố ý không đầy đủ.)

Ánh xạ này xảy ra tại biên dịch-thời gian - trình biên dịch xem \a và đặt bất kỳ giá trị ma thuật nào được sử dụng để đổ chuông.

Lưu ý rằng hầu hết các bộ ghi chú này có tương quan trực tiếp với mã kiểm soát ASCII. Ví dụ: \a sẽ ánh xạ tới 0x07 BEL. Một trình biên dịch có thể được viết cho một hệ thống sử dụng một cái gì đó khác với ASCII cho bộ ký tự máy chủ (ví dụ: EBCDIC). Hầu hết các mã điều khiển có các bộ nhớ cụ thể có thể được ánh xạ tới các mã điều khiển trong các bộ ký tự khác.

Huzzah! Tính di động!

Vâng, gần như vậy. Trong C, tôi có thể viết printf("\aHello, World!"); làm đổ chuông (hoặc tiếng bíp) và xuất ra một tin nhắn. Nhưng nếu tôi muốn in một thứ gì đó trên dòng tiếp theo, tôi vẫn cần phải biết nền tảng máy chủ nào cần chuyển sang dòng đầu ra tiếp theo. CR LF? CR? LF? NL? Thứ gì khác? Vì vậy, nhiều cho tính di động.

C có hai chế độ cho I/O: nhị phân và văn bản. Trong chế độ nhị phân, bất kỳ dữ liệu nào được gửi đều được truyền đi. Nhưng ở chế độ văn bản, có thời gian chạy dịch chuyển đổi một ký tự đặc biệt thành bất kỳ nền tảng máy chủ nào cần cho một dòng mới (và ngược lại).

Tuyệt vời, vậy nhân vật đặc biệt là gì?

Vâng, cũng phụ thuộc vào việc triển khai thực hiện, nhưng có cách triển khai độc lập để chỉ định: \n. Nó thường được gọi là "ký tự dòng mới".

Đây là một điểm nhỏ nhưng quan trọng:\n được ánh xạ tại thời gian biên dịch một thực hiện xác định giá trị nhân vật đó (trong chế độ văn bản) sau đó được ánh xạ một lần nữa tại thời gian chạy với nhân vật thực tế (hoặc chuỗi ký tự) được yêu cầu bởi nền tảng cơ bản để chuyển sang dòng tiếp theo.

\n khác với tất cả các dấu gạch chéo ngược khác vì có hai ánh xạ liên quan.Bản đồ hai bước này làm cho \n khác biệt đáng kể so với thậm chí \r, chỉ đơn giản là bản đồ thời gian biên dịch thành CR (hoặc mã điều khiển tương tự nhất trong bất kỳ bộ ký tự cơ bản nào).

Thao tác này sẽ thực hiện nhiều lập trình viên C và C++. Nếu bạn thăm dò ý kiến ​​100 người trong số họ, ít nhất 99 người sẽ cho bạn biết rằng \n có nghĩa là nguồn cấp dữ liệu dòng. Điều này không hoàn toàn đúng. Hầu hết (có thể tất cả) triển khai C và C++ sử dụng LF làm giá trị trung gian kỳ diệu cho \n, nhưng đó là chi tiết triển khai. Đó là khả thi cho một trình biên dịch để sử dụng một giá trị khác nhau. Trên thực tế, nếu tập hợp ký tự lưu trữ không phải là siêu dữ liệu ASCII (ví dụ: nếu đó là EBCDIC) thì \n gần như chắc chắn sẽ không phải là LF.

Vì vậy, trong C và C++:

  • \r đúng là một trở về vận chuyển.
  • \n là giá trị ma thuật được dịch (ở chế độ văn bản) tại thời gian chạy đến/từ ngữ nghĩa dòng mới của nền tảng máy chủ.
  • \r\n hầu như luôn là lỗi di động. Trong chế độ văn bản, điều này được dịch sang CR theo sau chuỗi mới của nền tảng - có thể không phải là mục đích. Trong chế độ nhị phân, điều này được dịch sang CR theo sau bởi một số giá trị ma thuật mà có thể không là LF - có thể không phải là mục đích.
  • \x0A là cách di động nhất để biểu thị LF ASCII, nhưng bạn chỉ muốn thực hiện điều đó ở chế độ nhị phân. Hầu hết các triển khai chế độ văn bản sẽ xử lý giống như \n.
4

\r được sử dụng để trỏ đến đầu dòng và có thể thay thế văn bản từ đó, ví dụ:

main() 
{ 
printf("\nab"); 
printf("\bsi"); 
printf("\rha"); 
} 

Tạo đầu ra này:

hai 

\n là dành cho dòng sản phẩm mới.

2

trong C# Tôi thấy họ sử dụng \ r \ n trong chuỗi.

1

\ r được sử dụng để vận chuyển trở lại. (Giá trị ASCII là 13) \ n được sử dụng cho dòng mới. (Giá trị ASCII là 10)

Các vấn đề liên quan