<ก่อนหน้านี้ | เนื้อหา | ถัดไป>
คำสั่งกลุ่มและเชลล์ย่อย
ทุบตี อนุญาตให้รวมกลุ่มคำสั่งเข้าด้วยกัน สามารถทำได้ด้วยวิธีใดวิธีหนึ่งจากสองวิธี ei- ด้วย a คำสั่งกลุ่ม หรือกับ เปลือกย่อย. ต่อไปนี้คือตัวอย่างไวยากรณ์ของแต่ละรายการ:
คำสั่งกลุ่ม:
{ command1; คำสั่ง2; [คำสั่ง3; ...] }
เปลือกย่อย:
(คำสั่ง 1; คำสั่ง 2; [คำสั่ง 3;...])
ทั้งสองรูปแบบต่างกันตรงที่คำสั่ง group ล้อมรอบคำสั่งด้วยเครื่องหมายปีกกา และ subshell ใช้วงเล็บ เป็นสิ่งสำคัญที่จะต้องทราบว่าเนื่องจากวิธีการ ทุบตี ใช้คำสั่งกลุ่ม วงเล็บต้องแยกออกจากคำสั่งด้วยช่องว่าง และคำสั่งสุดท้ายต้องสิ้นสุดด้วยเครื่องหมายอัฒภาคหรือขึ้นบรรทัดใหม่ก่อนวงเล็บปิด
คำสั่งกลุ่มและเชลล์ย่อยดีสำหรับอะไร แม้ว่าพวกเขาจะมีความแตกต่างที่สำคัญ (ซึ่งเราจะทำได้ในอีกสักครู่) พวกเขาทั้งคู่เคยชินกับการจัดการการเปลี่ยนเส้นทาง ลองพิจารณาส่วนของสคริปต์ที่ทำการเปลี่ยนเส้นทางในหลายคำสั่ง:
ls -l > output.txt
echo "รายการของ foo.txt" >> output.txt cat foo.txt >> output.txt
ls -l > output.txt
echo "รายการของ foo.txt" >> output.txt cat foo.txt >> output.txt
นี้ค่อนข้างตรงไปตรงมา สามคำสั่งพร้อมเอาต์พุตถูกเปลี่ยนเส้นทางไปยังไฟล์ชื่อ เอาต์พุต. txt. การใช้คำสั่งกลุ่ม เราสามารถเขียนโค้ดได้ดังนี้:
{ ls -l; echo "รายการของ foo.txt"; แมว foo.txt; } > output.txt
{ ls -l; echo "รายการของ foo.txt"; แมว foo.txt; } > output.txt
การใช้ subshell จะคล้ายกัน:
(ls -l; echo "Listing of foo.txt"; cat foo.txt) > output.txt
(ls -l; echo "Listing of foo.txt"; cat foo.txt) > output.txt
การใช้เทคนิคนี้ทำให้เราได้ช่วยตัวเองในการพิมพ์ แต่ที่ซึ่งคำสั่งกลุ่มหรือเชลล์ย่อยที่ส่องประกายจริงๆ ก็คือการใช้ไพพ์ไลน์ เมื่อสร้างไพพ์ไลน์ของคำสั่ง การรวมผลลัพธ์ของคำสั่งต่างๆ ไว้ในสตรีมเดียวมักจะมีประโยชน์ คำสั่งกลุ่มและเชลล์ย่อยทำให้สิ่งนี้ง่ายขึ้น:
{ ls -l; echo "รายการของ foo.txt"; แมว foo.txt; } | lpr
{ ls -l; echo "รายการของ foo.txt"; แมว foo.txt; } | lpr
ที่นี่เราได้รวมเอาท์พุตของคำสั่งทั้งสามของเราและไพพ์ลงในอินพุตของ LPR เพื่อทำการพิมพ์รายงาน
ในสคริปต์ที่ตามมา เราจะใช้คำสั่งกลุ่มและดูเทคนิคการเขียนโปรแกรมต่างๆ ที่สามารถใช้ร่วมกับอาร์เรย์ที่เชื่อมโยงได้ สคริปต์นี้เรียกว่า อาร์เรย์-2เมื่อกำหนดชื่อไดเร็กทอรีแล้ว จะพิมพ์รายการไฟล์ในไดเร็กทอรีพร้อมกับชื่อเจ้าของไฟล์และเจ้าของกลุ่ม ที่ส่วนท้ายของรายการ สคริปต์จะพิมพ์จำนวนไฟล์ที่เป็นของเจ้าของและกลุ่มแต่ละราย ที่นี่เราเห็นผลลัพธ์ (ย่อเพื่อความกระชับ) เมื่อสคริปต์ได้รับไดเรกทอรี
/usr/ถัง:
[me@linuxbox ~]$ อาร์เรย์-2 /usr/bin | ||
/usr/bin/2to3-2.6 | ราก | ราก |
/usr/bin/2to3 | ราก | ราก |
/usr/bin/a2p | ราก | ราก |
/usr/bin/เบราว์เซอร์ | ราก | ราก |
/usr/bin/aconnect | ราก | ราก |
/usr/bin/acpi_fakekey | ราก | ราก |
/usr/bin/acpi_listen | ราก | ราก |
/usr/bin/add-apt-repository | ราก | ราก |
. | ||
. | ||
. | ||
/usr/bin/zipgrep | ราก | ราก |
/usr/bin/zipinfo | ราก | ราก |
/usr/bin/zipnote | ราก | ราก |
/usr/bin/zip | ราก | ราก |
/usr/bin/zipsplit /usr/bin/zjsdecode.php /usr/bin/zsoelim | ราก ราก ราก | ราก ราก ราก | |
เจ้าของไฟล์: daemon : 1 | file (s) | ||
ราก : 1394 | file (s) |
เจ้าของกลุ่มไฟล์: crontab : 1 file(s) daemon : 1 file(s) lpadmin : 1 file(s) mail : 4 file(s) mlocate : 1 file(s) root : 1380 file(s) shadow : 2 file (s) ssh : 1 ไฟล์
tty : 2 ไฟล์
utmp : 2 ไฟล์
#! / bin / ทุบตี
#! / bin / ทุบตี
# array-2: ใช้อาร์เรย์เพื่อนับเจ้าของไฟล์
ประกาศ -A ไฟล์ file_group file_owner กลุ่มเจ้าของถ้า [[ ! -d "$1" ]]; แล้ว
echo "การใช้งาน: array-2 dir" >&2 ทางออก 1
fi
สำหรับฉันใน "$1"/*; ทำ Owner=$(stat -c %U "$i") group=$(stat -c %G "$i") files["$i"]="$i" file_owner["$i"]=$ เจ้าของ file_group["$i"]=$group ((++owners[$owner])) ((++groups[$group]))
ทำ
# แสดงรายการไฟล์ที่รวบรวม
{ สำหรับฉันใน "${files[@]}"; พิมพ์f "%-40s %-10s %-10s\n" \
"$i" ${file_owner["$i"]} ${file_group["$i"]} เสร็จแล้ว } | เรียงลำดับ
# array-2: ใช้อาร์เรย์เพื่อนับเจ้าของไฟล์
ประกาศ -A ไฟล์ file_group file_owner กลุ่มเจ้าของถ้า [[ ! -d "$1" ]]; แล้ว
echo "การใช้งาน: array-2 dir" >&2 ทางออก 1
fi
สำหรับฉันใน "$1"/*; ทำ Owner=$(stat -c %U "$i") group=$(stat -c %G "$i") files["$i"]="$i" file_owner["$i"]=$ เจ้าของ file_group["$i"]=$group ((++owners[$owner])) ((++groups[$group]))
ทำ
# แสดงรายการไฟล์ที่รวบรวม
{ สำหรับฉันใน "${files[@]}"; พิมพ์f "%-40s %-10s %-10s\n" \
"$i" ${file_owner["$i"]} ${file_group["$i"]} เสร็จแล้ว } | เรียงลำดับ
นี่คือรายการ (พร้อมหมายเลขบรรทัด) ของสคริปต์:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
27
28
29
30
31
32
33
34
35
36
37
38
39
40
เสียงสะท้อน
เสียงสะท้อน
#รายชื่อเจ้าของ
echo "เจ้าของไฟล์:"
{ สำหรับฉันใน "${!owners[@]}"; ทำ
printf "%-10s: %5d file(s)\n" "$i" ${owners["$i"]} done } | เรียงลำดับ
เสียงสะท้อน
# รายชื่อกลุ่ม
echo "เจ้าของกลุ่มไฟล์:"
{ สำหรับฉันใน "${!groups[@]}"; ทำ
printf "%-10s: %5d ไฟล์\n" "$i" ${groups["$i"]} done } | เรียงลำดับ
#รายชื่อเจ้าของ
echo "เจ้าของไฟล์:"
{ สำหรับฉันใน "${!owners[@]}"; ทำ
printf "%-10s: %5d file(s)\n" "$i" ${owners["$i"]} done } | เรียงลำดับ
เสียงสะท้อน
# รายชื่อกลุ่ม
echo "เจ้าของกลุ่มไฟล์:"
{ สำหรับฉันใน "${!groups[@]}"; ทำ
printf "%-10s: %5d ไฟล์\n" "$i" ${groups["$i"]} done } | เรียงลำดับ
มาดูกลไกของสคริปต์นี้กัน:
5 แนว: แอสโซซิเอทีฟอาเรย์ต้องสร้างด้วยเครื่องหมาย ประกาศ คำสั่งโดยใช้ -A
ตัวเลือก. ในสคริปต์นี้ เราสร้างห้าอาร์เรย์ดังนี้:
ไฟล์มีชื่อไฟล์ในไดเร็กทอรี จัดทำดัชนีโดยชื่อไฟล์ file_group ประกอบด้วยเจ้าของกลุ่มของแต่ละไฟล์ จัดทำดัชนีโดยชื่อไฟล์ file_owner ประกอบด้วยเจ้าของแต่ละไฟล์ จัดทำดัชนีตามชื่อไฟล์ กลุ่มมีจำนวนไฟล์ที่เป็นของเจ้าของกลุ่มที่ทำดัชนี มีจำนวนของไฟล์ที่เป็นของเจ้าของดัชนี
บรรทัดที่ 7-10: ตรวจสอบเพื่อดูว่ามีการส่งชื่อไดเร็กทอรีที่ถูกต้องเป็นพารามิเตอร์ตำแหน่งหรือไม่ หากไม่เป็นเช่นนั้น ข้อความการใช้งานจะปรากฏขึ้นและสคริปต์จะออกโดยมีสถานะออกเป็น 1
บรรทัดที่ 12-20: วนรอบไฟล์ในไดเร็กทอรี ใช้ stat คำสั่ง บรรทัดที่ 13 และ 14 จะแยกชื่อเจ้าของไฟล์และเจ้าของกลุ่ม และกำหนดค่าให้กับอาร์เรย์ที่เกี่ยวข้อง (บรรทัดที่ 16, 17) โดยใช้ชื่อไฟล์เป็นดัชนีอาร์เรย์ ในทำนองเดียวกันชื่อไฟล์นั้นถูกกำหนดให้กับ ไฟล์ อาร์เรย์ (บรรทัดที่ 15)
บรรทัดที่ 18-19: จำนวนไฟล์ทั้งหมดที่เป็นของเจ้าของไฟล์และเจ้าของกลุ่มเพิ่มขึ้นทีละหนึ่งไฟล์
บรรทัดที่ 22-27: รายการของไฟล์จะถูกส่งออก ทำได้โดยใช้การขยายพารามิเตอร์ "${array[@]}" ซึ่งขยายไปยังรายการองค์ประกอบอาร์เรย์ทั้งหมดโดยแต่ละองค์ประกอบถือเป็นคำที่แยกจากกัน ซึ่งช่วยให้มีความเป็นไปได้ที่ชื่อไฟล์อาจมีช่องว่างฝังตัว พึงทราบด้วยว่าวงทั้งหมดอยู่ในวงเล็บปีกกา ทำให้เกิดคำสั่งแบบกลุ่ม อนุญาตให้ส่งเอาต์พุตทั้งหมดของลูปไปที่ ประเภท สั่งการ. นี่เป็นสิ่งจำเป็นเนื่องจากไม่ได้เรียงลำดับการขยายตัวขององค์ประกอบอาร์เรย์
บรรทัดที่ 29-40: สองลูปนี้คล้ายกับลูปรายการไฟล์ ยกเว้นว่าใช้ "${!
array[@]}" ซึ่งขยายไปยังรายการดัชนีอาร์เรย์ แทนที่จะเป็นรายการองค์ประกอบอาร์เรย์