จุดประสงค์ของ bash Null-operator“:”, เครื่องหมายทวิภาคคืออะไร?


13

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



1
เหตุผลที่คุณอ้างถึงเป็นสิ่งสำคัญ ทำไมคุณต้องเพิ่มอีก
terdon

คำตอบ:


16

บางครั้งมีประโยชน์ในการอนุญาตให้มีการขยายผลข้างเคียง

ตัวอย่างเช่นการตั้งค่าเริ่มต้น

read -p "Enter your name: " name
: ${name:=John Doe}  # if the user entered an empty string
echo "$name"

2
คุณช่วยอธิบายสัญลักษณ์ทีละสัญลักษณ์ว่าบรรทัดที่สองทำงานได้อย่างไร?
Ruslan

อ่านเกี่ยวกับ:คำสั่งและการขยายพารามิเตอร์ในคู่มือทุบตี
เกล็นแจ็คแมน

4
หากต้องการร่างสิ่งที่ @glennjackman อ้างอิงบรรทัดที่สองเรียกคำสั่ง null: และ${name:="John Doe"}จะถูกขยายทำให้การมอบหมายเกิดขึ้นเนื่องจากถูกอ่านเป็นอาร์กิวเมนต์สำหรับ: หากไม่มี: เชลล์จะพยายามเรียกใช้ "John Doe" เป็นคำสั่งหรือค่า$nameหากตั้งค่าไว้แล้ว
imkendal

13

คุณยังสามารถใช้เพื่อลูปไม่มีที่สิ้นสุด:

while : ; do 
   # ....
done

4
แต่อาจwhile trueจะอ่านได้มากกว่าเพราะ (a) ใช้เครื่องหมายวรรคตอนน้อยกว่าและ (b) คล้ายกับภาษาที่ได้จากภาษา C
wchargin

9

คุณสามารถใช้มันเพื่อสร้างไฟล์โดยไม่ต้องรันโปรแกรม ::

: > /path/to/file

สิ่งนี้เร็วกว่าอนันต์มากกว่าtouch /path/to/file (เนื่องจากไม่จำเป็นต้องเรียกใช้touchโปรแกรม) และอาจพกพาได้ง่ายกว่าเล็กน้อย

> /path/to/file

ซึ่งดูเหมือนว่าจะทำงานกับหลาย ๆ ระบบ ในทำนองเดียวกันสามารถใช้เพื่อตรวจสอบว่าคุณมีสิทธิ์ในการเขียนไฟล์หรือไม่ :

if { : >> /path/to/file;} 2> /dev/null
then
    echo "writeable"
else
    echo "write permission denied"
fi

:แม้ว่าเรื่องนี้ยังทั่วไปจะสามารถทำได้โดยไม่ต้อง คำเตือน:

  • ไม่ได้ตรวจสอบว่าไฟล์มีอยู่แล้ว หากไม่เป็นเช่นนี้จะสร้างไฟล์หากได้รับอนุญาตให้ทำ
  • หากไฟล์ไม่มีอยู่และสคริปต์ของคุณไม่ได้รับอนุญาตให้สร้างไฟล์นี้จะรายงานว่า“ สิทธิ์การเขียนถูกปฏิเสธ”

(ดูคำถามที่เชื่อมโยงด้วยเหตุผลว่าทำไมเรื่องนี้จึงเชื่อถือได้มากกว่าif [ -w /path/to/file ])


5

ย้อนกลับไปใน Unix V6 และ Thompson Shell ส่วน:จริงแล้วถูกใช้เป็นส่วนหนึ่งของgotoแถลงการณ์ ตามคู่มือแล้วมันปรากฏในรุ่น 3 ของ Unix:

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

ทุกวันนี้bashมันถูกใช้เป็นโอเปอเรเตอร์ที่ไม่ต้องกลับไปสู่ความสำเร็จ แน่นอนถ้าคุณดูซอร์สโค้ดคุณจะเห็นว่าทั้งคู่trueและ:ใช้ฟังก์ชันเดียวกันint colon_builtin()ภายใต้ ไม่มี:คำสั่งที่ไม่ใช่บิลด์อินและ/bin/trueจริง ๆ แล้วเป็นคำสั่งที่ค่อนข้างใหญ่สำหรับสิ่งที่มันทำ

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


3

คุณสามารถใช้มันในการทดสอบเชิงบวกของifคำสั่งเมื่อคุณต้องการทำบางสิ่งในด้านลบ ตัวอย่างเช่น:

if [[ True == False ]]; then
    :
else
    echo "true <> flase"
fi

หากไม่มีการ:ทุบตีจะสร้างข้อผิดพลาดทางไวยากรณ์

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


คำตอบที่ดีแม้ว่ามันอาจจะไม่ชัดเจนในตอนแรกว่าสิ่งนี้มีประโยชน์มากที่สุดกับคำสั่งจริงในเงื่อนไขการทดสอบตัวอย่างเช่นif pgrep firefox >/dev/null ; then : ; else echo "Firefox not running"; fiจะแสดงข้อผิดพลาดเฉพาะในกรณีที่ firefox ไม่ทำงาน กล่าวอีกนัยหนึ่งเมื่อคุณต้องทำอะไรบางอย่างเฉพาะเมื่อคำสั่งมีข้อผิดพลาด ในวิธีนี้เทียบเท่ากับpgrep firefox || echo "Firefox not running"แม้ว่าจะอ่านได้มากขึ้นและอนุญาตให้ใช้คำสั่งเพิ่มเติม
Sergiy Kolodyazhnyy

0

ฉันเพิ่งใช้มันในสคริปต์ด้วยคำสั่ง SSH เพื่อป้องกันไม่ให้สคริปต์เกิดข้อผิดพลาด

ในกรณีนี้ฉันต้องการดูว่าผู้ใช้สามารถเชื่อมต่อกับชุดเซิร์ฟเวอร์ได้หรือไม่ หากการเชื่อมต่อเป็นปกติรีโมตโฮสต์จะดังขึ้นตกลง หากการเชื่อมต่อล้มเหลว SSH จะตอบกลับพร้อมข้อผิดพลาด อย่างไรก็ตามฉันต้องการให้สคริปต์ของฉันออกด้วย 0 และไม่ใช่ค่าของคำสั่ง SSH หากมันล้มเหลว เพื่อเป็นหลักผมกับดักข้อผิดพลาด SSH โดย ORing มันมีคำสั่งเป็นโมฆะ|| :ดูเหมือนว่านี้:

#!/bin/bash
for i in $(cat servers.txt); do
    echo -n "$i "; 
    ssh user@${i} 'echo OK' || :; 
done

ด้วยวิธีนี้ฉันจะได้รับผลลัพธ์จาก SSH แต่ไม่ใช่รหัสข้อผิดพลาด:

....
swl06 ok
swl07 ok
swl08 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
swl09 ok
swl10 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
....
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.