การขยายตัวของตัวแปรหอยและผลกระทบของ glob และแยกกับมัน


18

จริงๆแล้วโพสต์นี้มีคำถามสองข้อแยกกัน แต่ฉันคิดว่าการรวมกลุ่มพวกเขาเข้าด้วยกันจะให้บริบทเพิ่มเติม ฉันผ่านคำถามนี้ไปแล้วเกี่ยวกับเครื่องหมายคำพูดเกี่ยวกับตัวแปรแต่ฉันไม่เข้าใจว่าการขยายตัวของตัวแปรหมายถึงอะไรในตอนแรก ดังนั้นคำถามแรกของฉันคือ:

  1. อะไรคือการขยายตัวของตัวแปรใน Unix / Linux พูด?

ส่วนที่สองของคำถามของฉันเกี่ยวข้องกับข้อกำหนดต่อไปนี้:

  1. glob
  2. แยก

ค่าข้างต้นหมายถึงอะไรและมีผลต่อการขยายตัวของตัวแปรอย่างไร คำตอบสำหรับคำถามเดิมกล่าวถึงต่อไปนี้:

คิดว่าไม่มีเครื่องหมายคำพูด (ในบริบทรายการ) เป็นตัวดำเนินการแยก + glob

ราวกับว่า echo $ test เป็น echo glob (แยก ("$ test"))

ฉันไม่สามารถหาคำตอบใด ๆ ที่อยู่ตรงแนวคิดของglobbingและแยกแต่ใช้คำเหล่านั้นได้โดยตรงในการตอบคำถามอื่น ๆ เช่นนี้หนึ่งเมื่อเร็ว ๆ นี้


คำตอบ:


15

การขยายตัวแปร (คำมาตรฐานคือการขยายพารามิเตอร์และบางครั้งเรียกว่าการแทนที่ตัวแปร ) โดยทั่วไปหมายถึงการแทนที่ตัวแปรด้วยค่าของมัน อย่างแม่นยำยิ่งขึ้นมันหมายถึงการแทนที่การ$VARIABLEสร้าง (หรือ${VARIABLE}หรือ${VARIABLE#TEXT}หรือการสร้างอื่น ๆ ) ด้วยข้อความอื่น ๆ ซึ่งถูกสร้างขึ้นจากค่าของตัวแปร ข้อความอื่นนี้เป็นการขยายตัวของตัวแปร

กระบวนการขยายจะเป็นดังนี้ (ฉันพูดถึงกรณีทั่วไปเท่านั้นการตั้งค่าเชลล์และส่วนขยายบางอย่างแก้ไขพฤติกรรม)

  1. รับค่าของตัวแปรซึ่งเป็นสตริง หากไม่ได้กำหนดตัวแปรให้ใช้สตริงว่าง
  2. หากการสร้างมีการแปลงให้ใช้มัน ตัวอย่างเช่นถ้าการสร้างคือ${VARIABLE#TEXT}และค่าของตัวแปรเริ่มต้นด้วยTEXTลบออกTEXTจากจุดเริ่มต้นของค่า
  3. หากบริบทเรียกคำเดียว (ตัวอย่างเช่นภายในเครื่องหมายคำพูดคู่หรือในด้านขวามือของการมอบหมายหรือภายในเอกสารที่นี่) ให้หยุดที่นี่ มิเช่นนั้นให้ทำตามขั้นตอนต่อไป
  4. แบ่งค่าเป็นคำที่แยกกันในแต่ละลำดับของช่องว่าง (ตัวแปรIFSสามารถเปลี่ยนแปลงเพื่อแยกที่ตัวละครอื่นที่ไม่ใช่ช่องว่าง) ผลลัพธ์จึงไม่ได้เป็นสตริง แต่รายการของสตริง รายการนี้อาจว่างเปล่าถ้าค่ามีเพียงช่องว่างเท่านั้น
  5. รักษาองค์ประกอบของแต่ละรายการเป็นชื่อไฟล์รูปแบบสัญลักษณ์เช่นglob หากรูปแบบตรงกับบางไฟล์มันจะถูกแทนที่ด้วยรายการชื่อไฟล์ที่ตรงกันมิฉะนั้นจะถูกทิ้งให้อยู่คนเดียว

ตัวอย่างเช่นสมมติว่าตัวแปรfooมีa* b* c*และไดเรกทอรีปัจจุบันประกอบด้วยแฟ้มbar, และbaz pazจากนั้น${foo#??}จะขยายเป็นดังนี้:

  1. a* b* c*ค่าของตัวแปรเป็นสตริง 8 ตัวอักษร
  2. #??หมายถึงการตัดอักขระสองตัวแรกออกไปทำให้เกิดสตริงที่ b* c*มีความยาว6 อักขระ(พร้อมช่องว่างเริ่มต้น)
  3. หากการขยายอยู่ในบริบทรายการ (เช่นไม่ได้อยู่ในเครื่องหมายคำพูดคู่หรือบริบทที่คล้ายกันอื่น ๆ ) ดำเนินการต่อ
  4. แยกสตริงเป็นคำที่คั่นด้วยช่องว่างที่เกิดในรายชื่อของสองสตริง: และb*c*
  5. สตริงb*, ตีความว่าเป็นรูปแบบที่ตรงกับสองไฟล์: และbar bazสตริงc*ไม่ตรงกับไฟล์จึงถูกทิ้งให้อยู่คนเดียว barผลที่ได้คือรายชื่อของสามสตริง: baz, c*,

ตัวอย่างเช่นecho ${foo#??}พิมพ์bar baz c*(คำสั่งechoรวมอาร์กิวเมนต์ด้วยช่องว่างระหว่าง)

สำหรับรายละเอียดเพิ่มเติมดู:


2
โปรดทราบว่ามันเรียกว่าการขยายตัวพารามิเตอร์เพราะมันใช้กับตัวแปร ( $var) และประเภทอื่น ๆ ของพารามิเตอร์ชอบ$1, $#, $?, $-...
Stéphane Chazelas

12

glob / แยก

ฉันจะเอารูปกลม / แบ่งก่อน @ คำตอบของสเตฟานที่คุณเชื่อมโยงด้วยกำลังใช้คำเหล่านั้นในแง่ทั่วไป พวกเขาไม่ใช่คำสั่งจริงหรืออะไรอย่างนั้นเพียงแค่ดำเนินการหลอก

split("$test")จะแบ่งเนื้อหาของ "$ ทดสอบ" ขึ้นเป็น "อาร์เรย์" ขององค์ประกอบ

glob(...)แล้วจะดูแลเพื่อขยายใด ๆ ขององค์ประกอบเหล่านี้ที่มีเปลือก globbing ตัวอักษรเช่นหรือช่วง*[1-2]

ตัวอย่าง

สมมติว่าสตริงของเรา$testมีดังนี้

$ test="afile[1-2] afile[3-5]"

สมมติว่าเรามีไดเรกทอรีพร้อมไฟล์บางไฟล์

$ ls -1
afile1
afile2
afile3
afile4
afile5

ตอนนี้ถ้าเราพยายามที่จะสะท้อนโดยไม่ต้องพูดคุณควรสังเกตว่าสตริงของเราได้แยกช่องว่างแล้วตัวอักษรกลม ๆ ใด ๆ ได้ขยาย

$ echo $test
afile1 afile2 afile3 afile4 afile5

อย่างไรก็ตามถ้าเราต้องอ้างอิงตัวแปรเมื่อเราส่งมันเป็นอาร์กิวเมนต์ให้echoเราได้รับสตริงตัวอักษรดั้งเดิม

$ echo "$test"
afile[1-2] afile[3-5]

การขยายตัวของตัวแปร

การขยายตัวของคำศัพท์มีไว้เพื่อให้ครอบคลุมการดำเนินงานขั้นพื้นฐานที่เชลล์ดำเนินการโดยเป็นส่วนหนึ่งของการดำเนินงานพื้นฐาน เชลล์มีหน้าที่แยกวิเคราะห์อินพุตจากนั้นเรียกใช้งานอินพุตนี้เมื่อถือว่าถูกต้องทางไวยากรณ์

ในตัวอย่างก่อนหน้าของเรา เมื่อตัวแปร$testถูกนำเสนอให้กับechounquote เราได้บอกให้เชลล์ดำเนินการต่อไปและแยกข้อโต้แย้งเหล่านั้นออกแล้วทำให้มันกลม

เมื่อมีการอ้างถึงเราได้ทำการปิดการใช้งานคุณลักษณะนั้นโดยใช้ตัวแปรที่เราห่อด้วยเครื่องหมายคำพูดคู่

ตัวอย่าง

นี่คือตัวอย่างเพิ่มเติมของการโค้งงอและการแยก

glob / แยกเกิดขึ้นโดยอัตโนมัติ

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

glob / splitting ถูกปิดใช้งานผ่านการอ้างอิงสองครั้ง

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}

ฉันไม่ทราบว่าช่วงนั้นยังทำงานในลำดับที่กลับกัน
Joe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.