เมื่อฉันทำ
str="Hello World\n===========\n"
ฉันก็\n
พิมพ์ออกมาเหมือนกัน ฉันจะมีการขึ้นบรรทัดใหม่ได้อย่างไร
เมื่อฉันทำ
str="Hello World\n===========\n"
ฉันก็\n
พิมพ์ออกมาเหมือนกัน ฉันจะมีการขึ้นบรรทัดใหม่ได้อย่างไร
คำตอบ:
ในbash
คุณสามารถใช้ไวยากรณ์
str=$'Hello World\n===========\n'
เครื่องหมายคำพูดเดี่ยวที่นำหน้าด้วย a $
คือไวยากรณ์ใหม่ที่อนุญาตให้แทรกลำดับ escape ในสตริง
printf
builtin ยังช่วยให้สามารถบันทึกผลลัพธ์ที่ส่งออกไปยังตัวแปร
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
ถ้ามี