เมื่อฉันทำ
str="Hello World\n===========\n"
ฉันก็\nพิมพ์ออกมาเหมือนกัน ฉันจะมีการขึ้นบรรทัดใหม่ได้อย่างไร
เมื่อฉันทำ
str="Hello World\n===========\n"
ฉันก็\nพิมพ์ออกมาเหมือนกัน ฉันจะมีการขึ้นบรรทัดใหม่ได้อย่างไร
คำตอบ:
ในbashคุณสามารถใช้ไวยากรณ์
str=$'Hello World\n===========\n'
เครื่องหมายคำพูดเดี่ยวที่นำหน้าด้วย a $คือไวยากรณ์ใหม่ที่อนุญาตให้แทรกลำดับ escape ในสตริง
printfbuiltin ยังช่วยให้สามารถบันทึกผลลัพธ์ที่ส่งออกไปยังตัวแปร
printf -v str 'Hello World\n===========\n'
วิธีแก้ปัญหาทั้งสองไม่จำเป็นต้องใช้ subshell
หากในสิ่งต่อไปนี้คุณต้องพิมพ์สตริงคุณควรใช้เครื่องหมายคำพูดคู่ในตัวอย่างต่อไปนี้:
echo "$str"
เนื่องจากเมื่อคุณพิมพ์สตริงโดยไม่มีเครื่องหมายอัญประกาศบรรทัดใหม่จะถูกแปลงเป็นช่องว่าง
str=$'Hello World\n===========\n'เรียกว่าคืออะไร? การทดแทนตัวแปร?
str=$"My $PET eats:\n$PET food"? วิธีนี้ใช้ได้กับการเสนอราคาสองครั้ง
คุณสามารถใส่บรรทัดใหม่ตามตัวอักษรในเครื่องหมายคำพูดเดี่ยว (ในเชลล์สไตล์ Bourne / POSIX ใด ๆ )
str='Hello World
===========
'
สำหรับสตริงหลายบรรทัดเอกสารที่นี่มักจะสะดวก สตริงถูกป้อนเป็นอินพุตไปยังคำสั่ง
mycommand <<'EOF'
Hello World
===========
EOF
หากคุณต้องการเก็บสตริงในตัวแปรให้ใช้catคำสั่งในการทดแทนคำสั่ง อักขระขึ้นบรรทัดใหม่ที่ท้ายสตริงจะถูกปล้นโดยการทดแทนคำสั่ง หากคุณต้องการเก็บบรรทัดใหม่สุดท้ายให้วางจุกท้ายแล้วถอดออกหลังจากนั้น ในเชลล์ที่สอดคล้องกับ POSIX คุณสามารถเขียนstr=$(cat <<'EOF'); str=${str%a}ตามด้วย heredoc ได้ แต่ bash ต้องการให้ heredoc ปรากฏขึ้นก่อนที่จะปิดวงเล็บ
str=$(cat <<'EOF'
Hello World
===========
a
EOF
); str=${str%a}
ใน ksh, bash และ zsh คุณสามารถใช้$'…'แบบฟอร์มที่ยกมาเพื่อขยายเครื่องหมายทับขวาภายในเครื่องหมายคำพูด
str=$'Hello World\n===========\n'
str=$(cat <<'EOF')ไม่ทำงานตามที่เป็นอยู่ .. )ความต้องการที่จะอยู่ในบรรทัดถัดไปหลังจากสิ้นสุดเอกสารEOF.. แต่ถึงกระนั้นก็จะสูญเสียการขึ้นบรรทัดใหม่เนื่องจากคำสั่ง การแทน.
\nอินสแตนซ์ของtrailing (และนำหน้า) ในbashเมื่อจับที่นี่ doc ในตัวแปรพิจารณาIFS= read -r -d '' str <<'EOF'...เป็นทางเลือกแทนวิธี stopper (ดูคำตอบของฉัน)
คุณใช้ "echo" หรือไม่? ลอง "echo -e"
echo -e "Hello World\n===========\n"
echoจะเพิ่มหนึ่งรายการโดยอัตโนมัติเว้นแต่คุณจะระบุ -n (อย่างไรก็ตามความรุนแรงหลักของคำถามคือวิธีการขึ้นบรรทัดใหม่เหล่านี้เป็นตัวแปร)
bash, echo -e ไม่ทำงานบน OS X - นั่นเป็นเพราะechoเป็นทุบตีในตัว (มากกว่าปฏิบัติการภายนอก) -eและในตัวที่ไม่สนับสนุน (ในฐานะ builtin มันควรทำงานบนทุกแพลตฟอร์มที่ทุบตีทำงานโดยบังเอิญecho -eทำงานในkshและzshเกินไป) โดยคมชัด แต่ภายนอกechoยูทิลิตี้ บน OS X - /bin/echo- แน่นอนไม่ได้-eสนับสนุน
หากคุณต้องการบรรทัดใหม่ในสคริปต์ของคุณหลาย ๆ ครั้งคุณสามารถประกาศตัวแปรโกลบอลที่ถือบรรทัดใหม่ ด้วยวิธีนี้คุณสามารถใช้มันในสตริงที่มีเครื่องหมายคำพูดคู่ (การขยายตัวแปร)
NL=$'\n'
str="Hello World${NL} and here is a variable $PATH ===========${NL}"
$''ต้องมี subshell
"My dog eats:${NL}dog food"
จากการสนทนาทั้งหมดนี่เป็นวิธีที่ง่ายที่สุดสำหรับฉัน:
bash$ str="Hello World
==========="
bash$ echo "$str"
Hello World
===========
ก้องคำสั่งจะต้องใช้คำพูดสอง
เพื่อเติมเต็มคำตอบที่มีอยู่แล้วให้ดียิ่งขึ้น:
หากคุณกำลังใช้bashและคุณต้องการใช้การขึ้นบรรทัดใหม่ที่เกิดขึ้นจริงสำหรับการอ่าน , readเป็นตัวเลือกอีกจับนี่ doc ในตัวแปรซึ่ง (เช่นการแก้ปัญหาอื่น ๆ ที่นี่) ไม่จำเป็นต้องใช้ของ subshell
# Reads a here-doc, trimming leading and trailing whitespace.
# Use `IFS= read ...` to preserve it (the trailing \n, here).
read -r -d '' str <<'EOF' # Use `IFS= read ...` to preserve the trailing \n
Hello World
===========
EOF
# Test: output the variable enclosed in "[...]", to show the value's boundaries.
$ echo "$str"
[Hello World
===========]
-rตรวจสอบให้แน่ใจreadว่าไม่ได้ตีความอินพุต (โดยค่าเริ่มต้นมันจะรักษาแบ็คสแลชพิเศษ แต่ก็ไม่ค่อยจำเป็น)
-d ''ตั้งค่าตัวคั่น "บันทึก" เป็นสตริงว่างทำให้เกิดreadการอ่านอินพุตทั้งหมดในครั้งเดียว (แทนที่จะเป็นเพียงบรรทัดเดียว)
โปรดทราบว่าการออกจาก$IFS(ตัวคั่นเขตข้อมูลภายใน) เป็นค่าเริ่มต้น$' \t\n'(ช่องว่างแท็บขึ้นบรรทัดใหม่) ช่องว่างนำหน้าและต่อท้ายใด ๆจะถูกตัดออกจากค่าที่กำหนดให้$strซึ่งรวมถึงบรรทัดใหม่ของเอกสารที่นี่
(โปรดสังเกตว่าแม้ว่าร่างกายนี่ doc เริ่มต้นบนเส้นหลังตัวคั่นเริ่มต้น ( 'EOF'ที่นี่) ก็ไม่ได้มีนำขึ้นบรรทัดใหม่)
ปกตินี้เป็นพฤติกรรมที่ต้องการ แต่ถ้าคุณไม่ต้องการที่ท้ายบรรทัดใหม่ใช้IFS= read -r -d ''แทนเพียงread -r -d ''แต่ทราบว่าใด ๆช่องว่างชั้นนำและต่อท้ายจะถูกรักษาไว้แล้ว
(โปรดทราบว่าการเพิ่มIFS= ไปยังreadคำสั่งโดยตรงหมายความว่าการมอบหมายมีผลบังคับใช้ระหว่างคำสั่งนั้นเท่านั้นดังนั้นจึงไม่จำเป็นต้องเรียกคืนค่าก่อนหน้านี้)
การใช้ here-doc ยังช่วยให้คุณสามารถใช้การเยื้องเพื่อตั้งค่าสตริง multiline เพื่อให้สามารถอ่านได้:
# Caveat: indentation must be actual *tab* characters - spaces won't work.
read -r -d '' str <<-'EOF' # NOTE: Only works if the indentation uses actual tab (\t) chars.
Hello World
===========
EOF
# Output the variable enclosed in "[...]", to show the value's boundaries.
# Note how the leading tabs were stripped.
$ echo "$str"
[Hello World
===========]
การวาง-ระหว่าง<<และการเปิด here-doc delimiter ( 'EOF'ที่นี่) ทำให้อักขระแท็บนำหน้าถูกดึงออกจากเนื้อความ here-doc และแม้กระทั่งตัวคั่นการปิด แต่โปรดทราบว่าสิ่งนี้ใช้ได้กับอักขระแท็บจริงเท่านั้นไม่ใช่ช่องว่างดังนั้นหาก บรรณาธิการแปลกดปุ่มแท็บลงในช่องว่างจำเป็นต้องทำงานเพิ่มเติม
คุณต้องทำแบบนี้:
STR=$(echo -ne "Hello World\n===========\n")
ปรับปรุง:
ตามที่เฟร็ดชี้ให้เห็นวิธีนี้คุณจะหลุดตามท้าย "\ n" ในการกำหนดตัวแปรด้วยลำดับแบ็กสแลชที่ขยายให้ทำ:
STR=$'Hello World\n===========\n\n'
มาทดสอบกันเถอะ:
echo "[[$STR]]"
ให้เราตอนนี้:
[[Hello World
===========
]]
โปรดทราบว่า $ '' จะแตกต่างจาก $ "" ที่สองทำการแปลตามสถานที่ปัจจุบัน สำหรับ deital man bashดูในส่วนของข้อความใน
#!/bin/bash
result=""
foo="FOO"
bar="BAR"
result+=$(printf '%s' "$foo")$'\n'
result+=$(printf '%s' "$bar")$'\n'
echo "$result"
printf '%s' "$result"
เอาท์พุท:
FOO
BAR
FOO
BAR
result+=$foo$'\n'? $(printf %s "$foo")จะตัดแต่งอักขระบรรทัดใหม่ต่อท้ายด้วย$fooถ้ามี