นี่เป็นวิธีที่ฉันแนะนำให้คุณทำและฉันจะอธิบายว่าทำไม แต่ก่อนอื่นฉันต้องการพูดถึงเรื่องอื่น ...
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
วิธีแก้ปัญหาอื่น ๆ ที่แนะนำจำนวนมากที่นี่ดูเหมือนจะแนะนำว่าคุณสามารถส่งผลกระทบต่อเนื้อหาของตัวแปรเชลล์โดยการเปลี่ยนวิธีการของคุณในการขยาย ฉันรับรองได้ว่านี่ไม่ใช่กรณี
string="some stuff here \
some more stuff here."
echo $string ${#string}
echo "$string" "${#string}"
เอาท์พุท
some stuff here some more stuff here. 53
some stuff here some more stuff here. 53
สิ่งที่คุณเห็นข้างต้นคือการขยายตัวของการแยกฟิลด์ก่อนจากนั้นรายงานเกี่ยวกับการนับไบต์สำหรับตัวแปรต้นฉบับของการขยายแล้วการขยายที่คั่นด้วยเครื่องหมายคำพูดและการนับไบต์เดียวกัน ในขณะที่การส่งออกอาจแตกต่างกันเนื้อหาของตัวแปรเปลือก$string
ไม่เคยเปลี่ยนแปลงเลยยกเว้นการกำหนด
ยิ่งไปกว่านั้นถ้าคุณไม่เข้าใจว่าทำไมถึงเป็นเช่นนั้นคุณต้องพบกับความประหลาดใจที่น่ารังเกียจในไม่ช้า ลองอีกครั้ง แต่ในเงื่อนไขที่แตกต่างกันเล็กน้อย
IFS=sf
echo $string ${#string}
echo "$string" "${#string}"
เดียวกัน$string
- สภาพแวดล้อมที่แตกต่างกัน
เอาท์พุท
ome tu here ome more tu here. 53
some stuff here some more stuff here. 53
$IFS
แยกสนามเกิดขึ้นบนพื้นฐานของตัวคั่นฟิลด์ที่กำหนดไว้ใน มีตัวคั่นสองชนิด - $IFS
ช่องว่างและ$IFS
อย่างอื่น โดยค่าเริ่มต้น$IFS
จะมีการกำหนดแท็บพื้นที่ค่าขึ้นบรรทัดใหม่ - ซึ่งเป็น$IFS
ค่าช่องว่างที่เป็นไปได้สามค่า แม้ว่ามันจะเปลี่ยนแปลงได้ง่ายอย่างที่คุณเห็นด้านบนและอาจมีผลกระทบอย่างมากต่อการขยายฟิลด์ที่แยกออก
$IFS
ช่องว่างจะลบออกตามลำดับไปยังเขตข้อมูลเดียวและนี่คือเหตุผลที่echo
การขยายที่มีลำดับของช่องว่างใด ๆ เมื่อ$IFS
มีช่องว่างจะประเมินเป็นพื้นที่เดียว - เพราะecho
เชื่อมต่อข้อโต้แย้งบนช่องว่าง แต่ค่าที่ไม่ใช่ช่องว่างใด ๆ จะไม่ลบในลักษณะเดียวกันและตัวคั่นที่เกิดขึ้นแต่ละตัวจะได้รับเขตข้อมูลของตัวเองเสมอดังที่สามารถเห็นได้ในการขยายสิ่งด้านบน
นี่ไม่ใช่สิ่งที่เลวร้ายที่สุดของมัน $string
พิจารณาอื่น ๆ
IFS=$space$tab$newline
cd emptydir
string=" * * * \
* * * "
echo $string ${#string}
echo "$string" "${#string}"
เอาท์พุท
* * * * * * 30
* * * * * * 30
ดูโอเคใช่ไหม เรามาเปลี่ยนสภาพแวดล้อมอีกครั้ง
touch file1 file2 file3 file4 file5
echo $string ${#string}
echo "$string" "${#string}"
เอาท์พุท
file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 30
* * * * * * 30
ว้าว
โดยค่าเริ่มต้นเชลล์จะขยายชื่อไฟล์ globs หากสามารถจับคู่พวกเขา สิ่งนี้เกิดขึ้นหลังจากการขยายพารามิเตอร์และการแยกฟิลด์ในการวิเคราะห์คำสั่งและดังนั้นสตริงใด ๆ ที่ไม่ได้กล่าวถึงจะมีความเสี่ยงในลักษณะนี้ คุณสามารถสลับพฤติกรรมนี้ได้set -f
หากต้องการ แต่เชลล์ที่ทำงานร่วมกันได้กับ POSIX ใด ๆ จะทำงานโดยอัตโนมัติ
นี่คือประเภทของสิ่งที่คุณทำเมื่อคุณวางเครื่องหมายคำพูดในส่วนขยายเพื่อให้เหมาะกับการตั้งค่าการเยื้องของคุณ และในทุกกรณีโดยไม่คำนึงถึงพฤติกรรมการขยายของค่าที่แท้จริงสำหรับ$string
ยังคงเป็นสิ่งที่มันเป็นเมื่อคุณได้รับมอบหมายครั้งสุดท้าย งั้นลองกลับไปที่สิ่งแรก
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
echo "$var" "${#var}"
เอาท์พุท
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70
ฉันเชื่อว่านี่เป็นวิธีที่คุ้นเคยอย่างยิ่งในการปรับเปลี่ยนไวยากรณ์ของเชลล์ให้เข้ากับความต้องการของคุณ สิ่งที่ฉันทำข้างต้นจะกำหนดแต่ละสายแต่ละพารามิเตอร์ตำแหน่ง - ซึ่งสามารถแต่ละคนจะอ้างอิงจากจำนวนเหมือน$1
หรือ${33}
- แล้วการกำหนดค่าตัดแบ่งของพวกเขาไปโดยใช้พารามิเตอร์เปลือกพิเศษ$var
$*
วิธีการนี้ไม่ได้เป็นภูมิคุ้มกันที่จะ$IFS
ฉันใด แต่ถึงกระนั้นฉันก็พิจารณาความสัมพันธ์ของมันกับ$IFS
ผลประโยชน์เพิ่มเติมในส่วนนี้ พิจารณา:
IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"
echo "$space_split"
echo "$slash_split"
echo "$new_line_split"
เอาท์พุท
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like.
Arg 1: Line 1./Arg 2: Line 2./and so on for/as long as you might like.
Arg 1: Line 1.
Arg 2: Line 2.
and so on for
as long as you might like.
ในขณะที่คุณสามารถดู$*
เชื่อมหาเรื่องแต่ละคนในในไบต์แรกใน"$@"
$IFS
ดังนั้นการบันทึกค่าในขณะที่$IFS
กำหนดต่างกันจะได้รับตัวคั่นฟิลด์ที่แตกต่างกันสำหรับแต่ละค่าที่บันทึก สิ่งที่คุณเห็นด้านบนคือค่าตัวอักษรสำหรับแต่ละตัวแปร หากคุณไม่ต้องการตัวคั่นใด ๆ เลย:
IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"
เอาท์พุท
Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67