Newline ‘\r\n’ หรือ ‘\n’

Newline (อาจเรียกว่า line ending, end of line – EOL, line feed หรือ line break) คืออักขระพิเศษ (control character) สำหรับกำหนดการขึ้นบรรทัดใหม่ของ text file

ใน Windows จะใช้ “\r\n” ส่วนใน UNIX based OS ใช้ “\n” ในขณะที่ MacOS ก่อน OSX ใช้ “\r” ตั้งแต่ OSX ใช้ “\n” ซึ่งนำมาซึ่งความปวดหัวของบรรดาโปรแกรมเมอร์มาบ้างไม่มากก็น้อย วันนี้มาเล่าให้ฟังว่าเรื่องนี้มีความเป็นมายังไง

สมัยก่อนการพิมพ์ออกกระดาษเราใช้เครื่อง Teletype (โทรพิมพ์) คิดง่ายๆคือพิมพ์ดีดไฟฟ้าที่ส่งข้อมูลเข้าไปพิมพ์ได้ โดยอาจจะส่งจากคอมพิวเตอร์ในห้องเดียวกัน หรือส่งมาจากที่อื่นก็ได้ทั้งนั้น เครื่องพวกนี้จะ feed กระดาษเป็นม้วนผ่านลูกกลิ้งที่อยู่บนแคร่ เวลาพิมพ์ตัวพิมพ์ก็จะกระแทกรูปอักษรไปบนริบบิ้นหมึกให้กดบนกระดาษ พิมพ์ไปตัวนึง แคร่ก็ขยับไปอักษรนึง พอจะขึ้นบรรทัดใหม่ ก็ต้องหมุนลูกกลิ้ง (line feed) และผลักแคร่ไปขวาสุดเพื่อเริ่มพิมพ์บรรทัดใหม่จากทางซ้ายสุดของบรรทัด (carriage return)

เพราะฉะนั้นก็เลยต้องมีคำสั่งให้ หมุนลูกกลิ้ง (Line feed – LF) กับ ปัดแคร่ (Carriage Return – CR) นั้นเอง ปัญหาในช่วงทศวรรษที่ 60 ตอนนั้นคือเกิดมาตรฐานสองมาตรฐาน ISO บอกว่าใช้ตัวใดตัวหนึ่งหรือทั้งสองตัวก็ได้ ส่วน ASA บอกว่าต้องใช้คู่ (CR+LF)

การใช้งานเดี๋ยวๆก็มี เช่น การใช้ CR อย่างเดียว คือปัดแคร่ แต่ไม่ขึ้นบรรทัดใหม่ แล้วพิมพ์ข้อความบางส่วนซ้ำ เป็นการทำตัวหนา (Bold) ของสมัยนั้น ซึ่งเท่มาก หรือการขึ้นบรรทัดใหม่แต่พิมพ์ตรงตำแหน่งเดิม ไม่ย้อนไปขึ้นต้นบรรทัดก็ใช้ LF อย่างเดียว

เครื่องคอมพิวเตอร์ยุคต้นๆ เช่น DEC และ CP/M ใช้ CR+LF เพื่อให้ควบคุมการทำงานของ Teletype ได้ถูกต้อง ซึ่งก็ทำตามมาถึง DOS

ส่วน UNIX นั้นเลือกใช้ LF อย่างเดียวเพื่อขึ้นบรรทัดใหม่และปัดแคร่ โดยไปเพิ่ม CR ในระดับ driver เอา เพราะการใช้สองอักษรทำให้เขียนโปรแกรมยากไปโดยไม่จำเป็น การใช้ driver ทำก็เป็นเรื่องความ advance ของเทคโนโลยีของ UNIX ในตอนนั้น ซึ่งก็ใช้ตามกันมาจนถึง Linux

Macintosh รุ่นแรกๆ ใช้ CR ไม่เหมือนใคร มาจนถึง OS 9 ซึ่งไม่ต้องมีเหตุผลสำหรับศาสดา มาเปลี่ยนเป็นเหมือน UNIX ตอน OSX ซึ่งก็ไม่ต้องมีเหตุผลเช่นกัน

นอกจาก CR กับ LF แล้วก็ยังมี FF (Form Feed) สำหรับ feed กระดาษให้ขึ้นหน้าใหม่ และ BS (Back Space) สำหรับย้อนกลับไป 1 ตัวอักษร

ผมยังทันเขียนโปรแกรมคุมเครื่องพิมพ์แบบนี้อยู่ ตอนที่ทำ Word Processor ในเครื่อง IBM PC ที่เคยเล่าไปแล้ว ตอนนั้นมีเครื่องพิมพ์ IBM กับ Olympia ที่ขายดีมาก

พอถึงยุค Unicode ก็มีการกำหนดรหัส Unicode ตามอย่าง ASCII คือ LF = U+000A, CR = U+000D เพื่อให้การ convert text file จาก ASCII ไป Unicode ทำได้ง่าย

ในภาษา C กำหนดให้ ‘\n’ คือ Newline และ ‘\r’ คือ Carriage Return ทีนี้แหละปัญหาก็มา เพราะใน UNIX ใช้ขึ้นต้นบรรทัดใหม่ด้วย LF อย่างเดียวในการขึ้นบรรทัดใหม่ ซึ่งมันก็ต้องเป็น Newline ในภาษา C ซึ่งก็แปล ‘\n’ เป็น 0x0A และด้วยความปวดหัว โปรแกรมเมอร์ส่วนใหญ่ก็ใช้วิธี ช่างมัน เป็นอะไรก็ได้ เขียนโปรแกรมด้วย ‘\n’ มันก็ขึ้นบรรทัดใหม่ code ข้างหลังเป็นอะไรก็ช่างหัวมัน

พอข้อมูลจาก UNIX ซึ่งเป็น ‘\n’ ส่งไปทาง Internet protocol ทั้งหลาย Windows จะรับเป็น CR+LF แต่ถ้ารับด้วย UNIX จะได้เป็น LF อย่างเดียว ดังนั้นเพื่อหลีกเลี่ยงปัญหาก็ควรใช้ ‘\r\n’ เพื่อให้ปลายทางรับเหมือนกัน (แต่เพื่อนๆที่เป็น UNIX man มักจะดื้อเป็นพิเศษ)

Internet protocol เช่น HTTP, SMTP, FTP, IRC ใช้ CR+LF (‘\r\n’ – 0x0D 0x0A) ตอนใช้ email แรกๆ โปรแกรมยังแปลงกันไม่เก่ง ก็ทะเลาะกันประจำระหว่าคนใช้เครื่องคนละระบบ

ภาษาที่ใช้ Unicode เช่น Java, PHP, Python ก็จะแปลง ‘\r\n’ เป็น U+000D U+000A ถูกต้อง ส่วนภาษา C++ ก็ใช้ std::endl แทน ไม่สับสน

สมัยนี้ไม่ค่อยมีปัญหานักเพราะซอฟต์แวร์เก่งขึ้นมาก เล่าไว้ให้เพื่อนทราบที่มาครับ