การพิมพ์เครื่องหมายอัศเจรีย์เดียวทำอะไรใน Bash


20

Bash ใช้เครื่องหมายอัศเจรีย์สำหรับการขยายประวัติตามที่อธิบายในคำตอบสำหรับคำถามนี้ (เช่นsudo !!เรียกใช้บรรทัดคำสั่งก่อนหน้าด้วยsudo) อย่างไรก็ตามฉันไม่พบที่ใดก็ได้ที่อธิบายสิ่งที่เรียกใช้คำสั่งต่อไปนี้ (เช่นเครื่องหมายอัศเจรีย์):

!

ดูเหมือนว่าจะพิมพ์อะไรและออกด้วย 1 แต่ฉันไม่แน่ใจว่าทำไมมันถึงทำอย่างนั้น ฉันดูออนไลน์และในหน้า Bash man แต่ไม่พบอะไรเลยนอกจากความจริงที่ว่ามันเป็น "คำสงวน" - แต่เป็นเช่นนั้น}และใช้งานสิ่งนี้:

}

พิมพ์ข้อผิดพลาด:

bash: syntax error near unexpected token `}'

1
ไม่มีอะไร !ระบุว่า "เริ่มต้น" ของนิพจน์การขยายประวัติ
จอร์แดน

คำตอบ:


47

คนเดียว!ในช่วงเริ่มต้นของคำสั่งขัดแย้งออกจากสถานะของคำสั่งหรือท่อถ้าออกคำสั่ง0ก็จะพลิกเข้า1(ล้มเหลว) และถ้ามันออกมาไม่เป็นศูนย์ก็จะทำให้มันกลายเป็น0(ที่ประสบความสำเร็จ) ทางออก

การใช้งานนี้จัดทำเป็นเอกสารไว้ในคู่มือ Bash:

หากคำที่สงวนไว้ '!' มาก่อนท่อส่งสถานะออกคือการปฏิเสธตรรกะของสถานะทางออกตามที่อธิบายไว้ข้างต้น

!มีคำสั่งดังต่อไปนี้ไม่มีขัดแย้งคำสั่งที่ว่างเปล่าที่ไม่ทำอะไรเลยและผลตอบแทนที่แท้จริง (เทียบเท่าคำสั่ง ) มันกลับค่าจริงเป็นเท็จและออกด้วยสถานะ 1 แต่ไม่มีข้อผิดพลาด:


นอกจากนี้ยังมีการใช้งานอื่น ๆ!ภายในtestและ[[คำสั่งที่พวกเขาปฏิเสธการทดสอบตามเงื่อนไข สิ่งเหล่านี้ไม่เกี่ยวข้องกับสิ่งที่คุณเห็น ในคำถามของคุณและกรณีเหล่านั้นไม่เกี่ยวข้องกับการขยายประวัติและ!จะถูกแยกออกจากข้อกำหนดอื่น ๆ


5
+1 สำหรับคำตอบแรกเพื่ออธิบายสิ่งที่เรียกใช้จริงและสาเหตุที่อธิบายรหัสส่งคืน
Jeff Schaller

11

คุณสามารถค้นหาเครื่องหมายอัศเจรีย์จุดเดียวที่บันทึกไว้ในส่วน bash manual 3.2.2 Pipelines

หากคำที่สงวนไว้ '!' มาก่อนท่อส่งสถานะออกคือการปฏิเสธตรรกะของสถานะทางออกตามที่อธิบายไว้ข้างต้น

$ ! true; echo $?
1
$ ! false; echo $?
0

นอกจากนี้ในส่วน3.2.4.2 โครงสร้างแบบมีเงื่อนไข

! การแสดงออก

จริงถ้าการแสดงออกเป็นเท็จ


ส่วนที่4.1 Bourne Shell Builtins ด้วย

! expr

จริงถ้า expr เป็นเท็จ


ควรสังเกตว่า!จะเริ่มต้นการทดแทนประวัติเว้นแต่ตามด้วยเว้นวรรค, แท็บ, จุดสิ้นสุดของบรรทัด, '=' หรือ '(' (เมื่อเปิดใช้งานตัวเลือกเชลล์ extglob โดยใช้ shopt builtin)


0

เพราะ!ถูกนำมาใช้ในการเปรียบเทียบและวิธีการไม่ได้

ตัวอย่างเช่น:

a=3
b=2

[ $a -eq $b ] && echo "Equal"
[ ! $a -eq $b ] && echo "Not equal"
# of cause last comparison is possible to write as:
[ $a -eq $b ] || echo "Not equal"

[ $a -eq $b ]
echo $?
1
[ ! $a -eq $b ]
echo $?
0

1
นั่นคือความหมายของ!การเป็นอาร์กิวเมนต์ของtestคำสั่ง (รวมถึงเวอร์ชันในตัวของ bash) ไม่ใช่ความหมายของ!เมื่อใช้ในตำแหน่งคำสั่ง
Gilles 'ดังนั้นหยุดความชั่วร้าย'

1
จะต้อง! [...]ตรงกับคำถามในกรณีนี้
Michael Homer

เห็นด้วยกับ @Gilles และ @Michael Homer ผมรู้ว่าเป็น[] testฉันรีบหน่อย
Yurij Goncharuk

-2

! คำสั่งในตัวกลับความรู้สึกของไปป์ไลน์

การใช้งานอื่น ๆ :

#! คำสั่งในตัวเรียกใช้ล่ามที่มีชื่อเพื่อรันสคริปต์

! ตัวออกแบบเหตุการณ์ทำเครื่องหมายคำบรรทัดคำสั่งเป็นการทดแทนประวัติ

!= ผู้ประกอบการไม่เท่าเทียมกัน

$! ตัวแปรเชลล์ส่งคืนหมายเลขกระบวนการของคำสั่งพื้นหลังสุดท้าย


เพียงเพิ่มคุณสามารถใช้! $ เพื่อใช้คำสุดท้ายของคำสั่งก่อนหน้าดังนี้: ls -l /tmp cd !$ สิ่งนี้จะนำคุณไปยังไดเรกทอรี / tmp
Hopping Bunny

-3

! ตามด้วยสตริงดำเนินการคำสั่งก่อนหน้านี้ล่าสุด (ยังอยู่ในบัฟเฟอร์คำสั่ง) ที่เริ่มต้นด้วยสตริงที่กำหนด บางทีเชลล์เพิ่งพบว่าไม่มีคำสั่งก่อนหน้าเริ่มต้นด้วย <null>


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