Apa perbedaan antara \ r dan \ n?

245

Bagaimana \rdan \nberbeda? Saya pikir itu ada hubungannya dengan Unix vs Windows vs Mac, tapi saya tidak yakin persis bagaimana mereka berbeda, dan mana yang harus dicari / cocokkan di regex.

Sam Lee
sumber
1
Ini membutuhkan tag bahasa. Bahasa yang berbeda memiliki interpretasi yang berbeda pula '\n'.
Adrian McCarthy

Jawaban:

383

Mereka karakter yang berbeda. \radalah carriage return, dan \nmerupakan line feed.

Pada printer "lama", \rkirim print head kembali ke awal baris, dan \nlanjutkan kertas dengan satu baris. Karena itu keduanya diperlukan untuk mulai mencetak pada baris berikutnya.

Jelas itu agak tidak relevan sekarang, meskipun tergantung pada konsol Anda mungkin masih dapat digunakan \runtuk pindah ke awal baris dan menimpa teks yang ada.

Lebih penting lagi, Unix cenderung digunakan \nsebagai pemisah garis; Windows cenderung digunakan \r\nsebagai pemisah garis dan Mac (hingga OS 9) digunakan untuk digunakan \rsebagai pemisah garis. (Mac OS X adalah Unix-y, jadi gunakan \nsebagai gantinya; Mungkin ada beberapa situasi kompatibilitas di mana \rdigunakan sebagai gantinya.)

Untuk informasi lebih lanjut, lihat artikel baris baru Wikipedia .

EDIT: Ini peka bahasa. Dalam C # dan Java, misalnya, \n selalu berarti Unicode U + 000A, yang didefinisikan sebagai umpan baris. Dalam C dan C ++ airnya agak lebih keruh, karena artinya khusus untuk platform. Lihat komentar untuk detailnya.

Jon Skeet
sumber
22
+1 untuk orang tua. Output terminal digunakan untuk secara langsung mengontrol terminal elektronik yang dimuliakan (TTY Anda sebelum tampilan CRT yang mewah). Oleh karena itu, kami mendapatkan artefak yang luar biasa dari mereka yang berada dalam carriage return dan karakter baris baru (keduanya mungkin diperlukan, seperti yang disebutkan oleh Jon Skeet) dan hal-hal seperti \ a "bel", \ b "backspace" (jangan disamakan dengan "hapus "), dan semua karakter kontrol lain yang diperlukan untuk berkomunikasi dengan tty.
erjiang
35
+1 lain untuk orang tua. Anda masih dapat menekan Ctrl + G pada prompt perintah windows, tekan enter, dan speaker PC akan berbunyi bip. Itu sisa dari zaman kuno.
Dave Carlile
@Crappy Coding Guy benar-benar? Di Vista, hanya tertulis "'' tidak dikenali sebagai perintah internal atau eksternal"
Ponkadoodle
2
@AdrianMcCarthy: Tentu saja pertanyaannya tidak benar-benar menentukan C atau C ++ di sini. Dalam C #, misalnya \n adalah dijamin akan newline (bagian 2.4.4.4). Tentu saja, akan lebih baik jika OP telah menentukan platform ... Selain itu, saya pikir tingkat detail ini akan lebih membingungkan daripada berguna bagi seseorang yang hanya menanyakan perbedaannya.
Jon Skeet
2
@AdrianMcCarthy: Tapi di C # dan Java setidaknya, itu adalah feed baris. Ini adalah U + 000A, yang dinamai oleh Unicode sebagai "LINE FEED" (dan NEW LINE). Saya akan mengedit untuk menyebutkan kasus khusus C dan C ++, tapi saya benar-benar percaya itu adalah kasus khusus, bukan sebaliknya.
Jon Skeet
91

Dalam C dan C ++, \nadalah sebuah konsep, \radalah sebuah karakter, dan \r\n(hampir selalu) adalah bug portabilitas.

Pikirkan teletype lama. Print head diposisikan pada garis dan kolom. Saat Anda mengirim karakter yang dapat dicetak ke teletype, karakter itu dicetak pada posisi saat ini dan memindahkan kepala ke kolom berikutnya. (Secara konseptual ini sama dengan mesin tik, kecuali bahwa mesin tik biasanya memindahkan kertas sehubungan dengan print head.)

Ketika Anda ingin menyelesaikan garis saat ini dan mulai pada baris berikutnya, Anda harus melakukan dua langkah terpisah:

  1. pindahkan print head kembali ke awal baris, lalu
  2. pindahkan ke bawah ke baris berikutnya.

ASCII menyandikan tindakan ini sebagai dua karakter kontrol yang berbeda:

  • \x0D(CR) memindahkan print head kembali ke awal baris. (Unicode mengkodekan ini sebagai U+000D CARRIAGE RETURN.)
  • \x0A(LF) memindahkan print head ke baris berikutnya. (Unicode mengkodekan ini sebagai U+000A LINE FEED.)

Pada zaman teletype dan printer teknologi awal, orang sebenarnya mengambil keuntungan dari kenyataan bahwa ini adalah dua operasi terpisah. Dengan mengirim CR tanpa mengikutinya dengan LF, Anda dapat mencetak lebih dari garis yang sudah Anda cetak. Ini memungkinkan efek seperti aksen, tipe tebal, dan garis bawah. Beberapa sistem mencetak berulang beberapa kali untuk mencegah kata sandi terlihat di hardcopy. Pada terminal CRT serial awal, CR adalah salah satu cara untuk mengontrol posisi kursor untuk memperbarui teks yang sudah ada di layar.

Tetapi sebagian besar waktu, Anda sebenarnya hanya ingin pergi ke baris berikutnya. Daripada membutuhkan pasangan karakter kontrol, beberapa sistem hanya diperbolehkan satu atau yang lain. Sebagai contoh:

  • Varian Unix (termasuk versi modern Mac) hanya menggunakan karakter LF untuk menunjukkan baris baru.
  • File Macintosh lama (pra-OSX) hanya menggunakan karakter CR untuk menunjukkan baris baru.
  • VMS, CP / M, DOS, Windows, dan banyak protokol jaringan masih mengharapkan keduanya: CR LF.
  • Sistem IBM lama yang menggunakan EBCDIC terstandarisasi pada NL - karakter yang bahkan tidak ada dalam rangkaian karakter ASCII. Dalam Unicode, NL adalah U+0085 NEXT LINE, tetapi nilai EBCDIC yang sebenarnya adalah 0x15.

Mengapa sistem yang berbeda memilih metode yang berbeda? Hanya karena tidak ada standar universal. Di mana keyboard Anda mungkin mengatakan "Enter", keyboard lama digunakan untuk mengatakan "Kembali", yang merupakan kependekan dari Carriage Return. Bahkan, pada terminal serial, menekan Return sebenarnya mengirim karakter CR. Jika Anda menulis editor teks, akan tergoda untuk hanya menggunakan karakter itu ketika datang dari terminal. Mungkin itu sebabnya Mac lama hanya menggunakan CR.

Sekarang kami memiliki standar , ada lebih banyak cara untuk mewakili jeda baris. Meskipun sangat langka di alam liar, Unicode memiliki karakter baru seperti:

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

Bahkan sebelum Unicode muncul, para programmer menginginkan cara-cara sederhana untuk mewakili beberapa kode kontrol yang paling berguna tanpa perlu khawatir tentang rangkaian karakter yang mendasarinya. C memiliki beberapa urutan pelarian untuk merepresentasikan kode kontrol:

  • \a (untuk peringatan) yang membunyikan bel teletype atau membuat bip terminal
  • \f (untuk umpan formulir) yang pindah ke awal halaman berikutnya
  • \t (untuk tab) yang memindahkan print head ke posisi tab horizontal berikutnya

(Daftar ini sengaja tidak lengkap.)

Pemetaan ini terjadi pada waktu kompilasi - kompilator melihat \adan meletakkan nilai sihir apa pun yang digunakan untuk membunyikan bel.

Perhatikan bahwa sebagian besar mnemonik ini memiliki korelasi langsung dengan kode kontrol ASCII. Misalnya, \aakan memetakan ke 0x07 BEL. Kompiler dapat ditulis untuk sistem yang menggunakan sesuatu selain ASCII untuk set karakter host (misalnya, EBCDIC). Sebagian besar kode kontrol yang memiliki mnemonik tertentu dapat dipetakan untuk mengontrol kode dalam rangkaian karakter lain.

Sabas! Portabilitas!

Hampir saja. Dalam C, saya bisa menulis printf("\aHello, World!");yang membunyikan bel (atau berbunyi bip) dan mengeluarkan pesan. Tetapi jika saya ingin mencetak sesuatu pada baris berikutnya, saya masih perlu tahu apa yang dibutuhkan platform host untuk pindah ke baris output berikutnya. CR LF? CR? LF? NL? Sesuatu yang lain Begitu banyak untuk portabilitas.

C memiliki dua mode untuk I / O: biner dan teks. Dalam mode biner, data apa pun yang dikirim akan dikirim apa adanya. Namun dalam mode teks, ada terjemahan run-time yang mengubah karakter khusus menjadi apa pun yang dibutuhkan platform host untuk baris baru (dan sebaliknya).

Bagus, jadi apa karakter spesialnya?

Nah, bahwa implementasi ini tergantung, juga, tapi ada cara pelaksanaan-independen untuk menentukan hal itu: \n. Biasanya disebut "karakter baris baru".

Ini adalah poin yang halus tetapi penting: \n dipetakan pada waktu kompilasi ke nilai karakter yang ditentukan implementasi yang (dalam mode teks) kemudian dipetakan lagi pada saat run time ke karakter aktual (atau urutan karakter) yang diperlukan oleh platform yang mendasari untuk bergerak ke baris berikutnya.

\nberbeda dari semua literal backslash lainnya karena ada dua pemetaan yang terlibat. Pemetaan dua langkah ini membuat \nperbedaan yang signifikan dari genap \r, yang hanya merupakan pemetaan waktu kompilasi ke CR (atau kode kontrol yang paling mirip dalam apa pun karakter yang mendasarinya)

Ini menjebak banyak programmer C dan C ++. Jika Anda melakukan polling 100, setidaknya 99 akan memberi tahu Anda itu \nberarti umpan baris. Ini tidak sepenuhnya benar. Sebagian besar (mungkin semua) implementasi C dan C ++ menggunakan LF sebagai nilai perantara ajaib untuk \n, tetapi itu adalah detail implementasi. Layak bagi kompiler untuk menggunakan nilai yang berbeda. Bahkan, jika set karakter host bukan superset ASCII (misalnya, jika itu EBCDIC), maka \nhampir pasti tidak akan menjadi LF.

Jadi, dalam C dan C ++:

  • \r secara harfiah pengembalian kereta.
  • \nadalah nilai ajaib yang diterjemahkan (dalam mode teks) saat run-time ke / dari semantik baris baru platform host.
  • \r\nhampir selalu merupakan bug portabilitas. Dalam mode teks, ini akan diterjemahkan ke CR diikuti oleh urutan baris baru platform - mungkin bukan yang dimaksudkan. Dalam mode biner, ini akan diterjemahkan ke CR diikuti oleh beberapa nilai ajaib yang mungkin bukan LF - mungkin bukan yang dimaksudkan.
  • \x0Aadalah cara yang paling portabel untuk menunjukkan LF ASCII, tetapi Anda hanya ingin melakukannya dalam mode biner. Sebagian besar implementasi mode teks akan memperlakukannya seperti itu \n.
Adrian McCarthy
sumber
Datang di pos ini sambil mencoba mencari cara untuk membagi input <textarea> dengan Python, dan \r\nsebenarnya satu-satunya cara saya bisa membagi baris menjadi elemen daftar yang terpisah. Itu membuat saya bertanya-tanya apakah ini adalah beberapa artefak HTML aneh, atau apakah itu ada hubungannya dengan cara Python menelan string dari requestobjek saya .
Pat Jones
11
  • "\ r" => Kembali
  • "\ n" => Baris Baru atau Linefeed (semantik)

  • Sistem berbasis Unix hanya menggunakan "\ n" untuk mengakhiri baris teks.

  • Dos menggunakan "\ r \ n" untuk mengakhiri baris teks.
  • Beberapa mesin lain hanya menggunakan "\ r". (Commodore, Apple II, Mac OS sebelum OS X, dll.)
NoMoreZealots
sumber
5

\r digunakan untuk menunjuk ke awal baris dan dapat mengganti teks dari sana, misalnya

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

Menghasilkan output ini:

hai

\n untuk baris baru.

DAYA PHILIP
sumber
4

Singkatnya memiliki nilai ASCII 13 (CR) dan \ n memiliki nilai ASCII 10 (LF). Mac menggunakan CR sebagai pembatas garis (setidaknya, itu pernah terjadi sebelumnya, saya tidak yakin untuk mac modern), * nix menggunakan LF dan Windows menggunakan keduanya (CRLF).

Josip Medved
sumber
1
Sistem Mac OS X menggunakan LF secara default (karena didasarkan pada BSD Unix).
dreamlax
3

Selain jawaban @Jon Skeet:

Secara tradisional Windows telah menggunakan \ r \ n, Unix \ n dan Mac \ r, namun Mac yang lebih baru menggunakan \ n karena berbasis unix.

Greg
sumber
2

di C # saya menemukan mereka menggunakan \ r \ n dalam sebuah string.

Wesley
sumber
2

Carriage Return; \ n adalah Baris Baru (Umpan Baris) ... tergantung pada OS untuk setiap arti. Baca artikel ini untuk informasi lebih lanjut tentang perbedaan antara '\ n' dan '\ r \ n' ... dalam C.

Nathan Loding
sumber
1

digunakan untuk carriage return. (Nilai ASCII adalah 13) \ n digunakan untuk baris baru. (Nilai ASCII adalah 10)

Manjeet Kumar
sumber