ข้อผิดพลาดที่สำคัญสองประการ
ซึ่งถูกปฏิเสธโดยคำตอบอื่น ๆ จนถึง:
- การลบบรรทัดใหม่ต่อท้ายจากการขยายคำสั่ง
- การลบอักขระ NUL
การลบบรรทัดใหม่ต่อท้ายจากการขยายคำสั่ง
นี่เป็นปัญหาสำหรับ:
value="$(cat config.txt)"
โซลูชันประเภท แต่ไม่ใช่สำหรับread
โซลูชันพื้นฐาน
การขยายคำสั่งลบบรรทัดใหม่ต่อท้าย:
S="$(printf "a\n")"
printf "$S" | od -tx1
ขาออก:
0000000 61
0000001
นี่เป็นการแบ่งวิธีที่ไร้เดียงสาของการอ่านจากไฟล์:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
วิธีแก้ปัญหา POSIX: ผนวกอักขระพิเศษในการขยายคำสั่งและลบในภายหลัง:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
ขาออก:
0000000 61 0a 0a
0000003
วิธีแก้ปัญหาเกือบ POSIX: เข้ารหัส ASCII ดูด้านล่าง
การลบอักขระ NUL
ไม่มีสติวิธีทุบตีเพื่อเก็บอักขระ NUL ในตัวแปรคือ
สิ่งนี้มีผลต่อทั้งการขยายตัวและread
การแก้ปัญหาและฉันไม่รู้วิธีแก้ปัญหาที่ดีสำหรับมัน
ตัวอย่าง:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
ขาออก:
0000000 61 00 62
0000003
0000000 61 62
0000002
ฮา NUL ของเราหายไปแล้ว!
วิธีการแก้ปัญหา:
การเข้ารหัส ASCII ดูด้านล่าง
ใช้$""
ตัวอักษรนามสกุลทุบตี:
S=$"a\0b"
printf "$S" | od -tx1
ใช้ได้กับตัวอักษรเท่านั้นดังนั้นจึงไม่มีประโยชน์สำหรับการอ่านจากไฟล์
วิธีแก้ปัญหาสำหรับข้อผิดพลาด
เก็บไฟล์ที่เข้ารหัสรุ่น uuencode base64 ในตัวแปรและถอดรหัสก่อนการใช้งานทุกครั้ง:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
เอาท์พุท:
0000000 61 00 0a
0000003
uuencode และ udecode คือPOSIX 7แต่ไม่ใช่ใน Ubuntu 12.04 โดยค่าเริ่มต้น ( sharutils
แพ็คเกจ) ... ฉันไม่เห็นทางเลือก POSIX 7 สำหรับ<()
ส่วนขยายการทดแทนกระบวนการทุบตียกเว้นการเขียนไปยังไฟล์อื่น ...
แน่นอนว่ามันช้าและไม่สะดวกดังนั้นฉันเดาว่าคำตอบที่แท้จริงคือ: อย่าใช้ Bash ถ้าไฟล์อินพุตอาจมีอักขระ NUL
cat
หรือ$(<someFile)
จะทำให้เกิดผลลัพธ์ที่ไม่สมบูรณ์ (ขนาดน้อยกว่าไฟล์จริง)