หมายความว่าอะไร $!


32

ฉันกำลังติดตามผ่านบทช่วยสอนและกล่าวถึงการเรียกใช้คำสั่งนี้:

sudo chmod 700 !$

!$ฉันไม่คุ้นเคยกับ มันหมายความว่าอะไร?


5
โดยทั่วไปแล้วจะปลอดภัยที่จะลองทำechoบางสิ่งหากคุณไม่แน่ใจว่าจะทำอะไร
Shadur

8
@Shadur ไม่เสมอไป echo $(rm -rf /)
cjm

1
@cjm ยกเว้นว่าคุณอยู่ในระบบที่เก่ามากคุณจะต้องมี--no-preserve-rootตัวเลือกในนั้นและหากคุณเห็นคำว่า "ไม่สงวน" ในโปรแกรมคุณควรคิดอย่างรอบคอบเกี่ยวกับสิ่งที่มันทำ
wchargin

4
@WChargin ระวังให้ดีมากสมมติว่า "เก่าจริงๆ" และ "ไม่ใช้ Linux / ไม่ใช้ GNU coreutils" เป็นสิ่งเดียวกัน พวกเขาไม่ได้
Chris Down

คำตอบ:


44

โดยทั่วไปมันเป็นอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้า

!$คือ "end" ของคำสั่งก่อนหน้า ลองพิจารณาตัวอย่างต่อไปนี้: เราเริ่มต้นด้วยการค้นหาคำในไฟล์:

grep -i joe /some/long/directory/structure/user-lists/list-15

หาก joe อยู่ในรายการผู้ใช้นั้นเราต้องการลบเขาออกจากรายการ เราสามารถเริ่มต้นด้วย vi ด้วยต้นไม้ไดเรกทอรีที่ยาวเป็นอาร์กิวเมนต์หรือง่ายๆตามvi !$ที่ bash ขยายไปถึง:

vi /some/long/directory/structure/user-lists/list-15

(ที่มา ; คู่มือที่มีประโยชน์โดยวิธีการ)


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

ตัวอย่างเช่นพิจารณาการกดแป้น

  • echo Foo Enter echo !$ Jar Enter Up Enter; และ

  • echo Foo Enter echo $_ Jar Enter Up Enter.

(ตัวละครที่เปลี่ยนแปลงเท่านั้นคือ $!และ$_ตรงกลาง)

ในอดีตเมื่อคุณกดUpบรรทัดคำสั่งจะอ่านecho Foo Jarดังนั้นบรรทัดสุดท้ายเขียนไป stdout Foo Jarคือ

ในตอนหลังเมื่อคุณกดUpบรรทัดคำสั่งจะอ่านecho $_ barแต่ตอนนี้$_มีค่าที่แตกต่างจากที่เคยทำก่อนหน้านี้จริง ๆ แล้ว$_คือตอนนี้Jarดังนั้นบรรทัดสุดท้ายเขียนไป stdout Jar Jarคือ

ผลที่ตามมาอีกประการหนึ่งคือ_สามารถใช้ในการขยายพารามิเตอร์อื่น ๆ เช่นลำดับของคำสั่ง

printf '%s '    isomorphism
printf '%s\n'   ${_%morphism}sceles

isomorphism isoscelesพิมพ์ แต่ไม่มี${!$%morphism}การขยาย ""

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเฟสของการขยายใน Bash ให้ดูในEXPANSIONส่วนของman 1 bash(ซึ่งเรียกว่าการขยายเชลล์ในรุ่นออนไลน์) HISTORY EXPANSIONส่วนแยกต่างหาก


6
ดี ดีแล้วที่รู้. สิ่งที่ดีคือการแลกเปลี่ยนแบบสแต็ก การค้นหาสิ่งที่ชอบของ Google เป็นเรื่องยาก!$
Andrew

4
BTW, ในบรรทัดคำสั่งคุณสามารถแทรกอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้าโดยมักจะถูกผูกไว้กับinsert-last-argument M-.
choroba

1
@Andrew โปรดจำไว้ว่าให้ยอมรับสิ่งนี้หากตอบคำถามของคุณ การยอมรับและการถอนเงินมากกว่าการโพสต์ความคิดเห็นเป็นวิธีที่แสดงความขอบคุณในเครือข่าย SE ดูที่นี่สำหรับท่าทาง "เป็นทางการ"
terdon

1
@Andrew FYI ฉันค้นหา Google เพื่อหา "bash bang dollar" และได้ผลลัพธ์ที่ดีรวมถึงลิงค์นี้เป็นรายการที่สาม
wchargin

1
@terdon ฉันพยายามยอมรับคำตอบเมื่อคืน แต่มันก็เร็วมากจนฉันถูกบังคับให้ต้องรอรับมัน
แอนดรู

4

การพูดอย่างเคร่งครัด!$เป็นคำสุดท้ายของคำสั่งสุดท้ายจากรายการประวัติ

word - ลำดับของอักขระที่ถือว่าเป็นหน่วยโดยเชลล์ คำอาจไม่รวมถึงตัวอักษรที่ไม่มีเครื่องหมายอัญประกาศ

metacharacter - ตัวละครที่แยกคำออกมา อักขระเมตาอักขระว่างเปล่าหรือหนึ่งในตัวละครต่อไปนี้: '|', '&', ';', '(', ')', '<' หรือ '>'

blank - ช่องว่างหรืออักขระแท็บ

ตัวอย่าง:

set -o history # enable command history
set -o histexpand # enable ! style history substitution

HISTSIZE=10

# save all lines on the history list    
HISTCONTROL=
HISTIGNORE=

date
echo !$ # prints date

date>/dev/null
echo !$ # prints /dev/null

echo a b c>/dev/null
echo !$ # prints /dev/null

HISTCONTROL=ignorespace # lines which begin with a space character are not saved in the history list
echo a b c
 echo d e f # space at the beginning
echo !$ # prints c


-3

!$ จะให้คำสั่งสุดท้ายที่ใช้กับผู้ใช้นั้นโดยเฉพาะ ....

คุณสามารถค้นหาประวัติคำสั่งที่ใช้ก่อนหน้านี้โดยใช้ historyคำสั่ง ... ลองใช้ ....

หมายเหตุ: สำหรับผู้ใช้เฉพาะคำสั่งทั้งหมดที่ใช้ก่อนหน้านี้จะถูกเก็บไว้ภายใต้ไฟล์ประวัติทุบตี


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