Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม Bash

การพิมพ์บรรทัดใหม่ใน Output บรรทัดคำสั่ง: คู่มือปฏิบัติจริง

เรื่องน่าประหลาด: ทำให้คอมพิวเตอร์แสดง Output ที่มนุษย์อ่านง่าย — ไม่ใช่เรื่องง่ายเลย ด้วย Standard Streams และ Stdout โปรแกรมสื่อสารกันด้วย Text Streams แตการ "Humanize" และแสดง Stdout นั้นเป็นอีกเรื่อง

ตั้งแต่ ASCII บนจอ Video ไปจนถึง Shell Commands สมัยใหม่อย่าง echo และ printf — ทุกอย่างพยายามแก้ปัญหานี้ แต่ยังมี "Quirks" เหลืออยู่ ตัวอย่างชัดเจน: การขยาย Escape Sequence \n เพื่อพิมพ์ Newline — ทำได้หลายวิธี แต่ละวิธีมีประวัติและข้อซับซ้อนเฉพาะตัว

ใช้ echo

ตั้งแต่ Multics ถึง Unix-like สมัยใหม่ echo เป็นเครื่องมือคุ้นเคยสำหรับ "Hello world!" แต่ Implementation ไม่สม่ำเสมอข้าม OS:

  • บางระบบ: echo ขยาย Escape Sequences อัตโนมัติ
  • บางระบบ: ต้องใช้ -e ถึงจะขยาย
echo "the study of European nerves is \neurology"
# the study of European nerves is \neurology  (ไม่ขยาย)

echo -e "the study of European nerves is \neurology"
# the study of European nerves is
# eurology  (ขยายได้)

เพราะ Inconsistencies นี้ → echo ถือว่า Non-portable นอกจากนี้ยังอ่อนไหวต่อ Shell Injection ผ่าน Command Substitution

ระบบสมัยใหม่เก็บ echo ไว้เพื่อ Backward Compatibility — POSIX แนะนำให้ใช้ printf ในโปรแกรมใหม่

ใช้ printf

ตั้งแต่ Unix 4th Edition printf เป็น Portable และดียกว่า echo ใช้ Format Specifiers จัดรูปแบบ Output

ตีความ Backslash Escapes: ใช้ %b — \n ให้นิ่งบรรทัดใหม่ท้าย:

printf "%b\n" "Many females in Oble are \noblewomen"
# Many females in Oble are
# oblewomen

printf มี Options เพิ่มเติมมาก — แทนที่ echo ได้สมบูรณ์ แต่ก็ยังมีช่องโหว่ Uncontrolled Format String Attack — ต้องจัดการ User Input อย่างระมัดระวัง

เก็บ Newlines ใน Variables

ANSI C Standard (1983) เพื่อ Portability ระหว่าง Compilers — ANSI-C Quoting $'...' ขยาย Escape Sequences ใน Output ตามมาตรฐาน

เก็บสตริงที่มี Newlines ใน Variable แล้วพิมพ์ด้วย Newlines จริง:

puns=$'\number\narrow\nether\nice'
printf "%b\n" "These words started with n but don't make $puns"
# These words started with n but don't make
# umber
# arrow
# ether
# ice

Variable ที่ขยายแล้วถูก Single-quote → ส่งต่อให้ printf ตรงๆ จัดการ Input ให้ดีเสมอ

โบนัส: Shell Parameter Expansion

ในบทความ Bash และ Braces เคยครอบคลุม Shell Parameter Expansion — Expansion หนึ่งคือ ${parameter@operator} สำหรับขยาย Escape Sequences

ใช้ printf กับ %s (Print as String) และ Operator E จะขยาย Escape Sequences ใน Variable:

printf "%s\n" ${puns@E}
# umber
# arrow
# ether
# ice

ความท้าทายที่ต่อเนื่อง: "พูดภาษามนุษย์"

String Interpolation ยังเป็นปัญหายากสำหรับ Programmers — นอกจากภาษา/Shell ไม่ตกลงกันใน Placeholders การ Escape ถูกต้องต้องการรายละเอียด

Interpolation ผิด → Output ดูขี้เหล็ก และอาจเปิดโอกาส Security Vulnerabilities (Injection Attacks) จนกว่า Terminal รุ่นต่อไปจะให้พูด Emoji ได้ — เราต้องระมัดระวังตอนพิมพ์ Output ให้มนุษย์อ่าน