แป้นพิมพ์ลัดของ Bash สำหรับ! *


8

ใน Bash มีโอเปอเรเตอร์ที่ใช้งานง่ายบางส่วนเพื่อทำซ้ำส่วนของคำสั่งสุดท้าย:

  • !^ ขยายไปยังอาร์กิวเมนต์แรกของคำสั่งก่อนหน้าเช่น

    $ echo one "two three"
    one two three
    $ echo !^
    echo one
    one
  • !$ ขยายไปยังอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้าเช่น

    $ echo one "two three"
    one two three
    $ echo !$
    echo "two three"
    two three
  • !* ขยายไปยังข้อโต้แย้งทั้งหมดของคำสั่งก่อนหน้าเช่น

    $ echo one "two three"
    one two three
    $ echo !*
    echo one "two three"
    one two three

(เท่าที่ผมเข้าใจเหล่านี้เป็นน้ำตาลประโยคสำหรับ!!:^, !!:$และ!!:*ตามลำดับซึ่ง!!เป็นตัวกำหนดเหตุการณ์ที่ขยายคำสั่งก่อนหน้านี้และ^, $และ*มี designators คำให้ดูทุบตี Reference Manualหรือman bash.)

สิ่งเหล่านี้มักจะมีประโยชน์มาก แต่มันจะยิ่งเย็นขึ้นด้วยแป้นพิมพ์ลัด:

  • เมื่อคุณกดAlt+ .หรือAlt+ _อาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้านี้จะถูกแทรกในคำสั่งปัจจุบันเช่นเดียวกับที่คุณเขียน!$ที่จุดนั้น

  • นอกจากนี้ยังเป็นไปได้ที่จะกดAlt+ Ctrl+ yเพื่อแทรกอาร์กิวเมนต์แรกของคำสั่งก่อนหน้าราวกับว่าคุณเขียน!^ที่จุดนั้น

(ดูGNU Readline Libraryหรือinfo readline.)

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

มีทางลัดไหม? ถ้าไม่เป็นไปได้หรือไม่ที่จะกำหนดค่าไลบรารี readline เพื่อเพิ่มหนึ่งรายการและอย่างไร


AFAIK แป้นพิมพ์ลัดได้รับการจัดการโดยเทอร์มินัลอีมูเลเตอร์ ดังนั้นฉันคิดว่าคุณกำลังใช้ gnome-terminal?
เซ

1
ในzshหากคุณพิมพ์echo !*แล้วกด TAB คุณจะมีเอฟเฟกต์ที่ต้องการ โดยทั่วไป TAB ขณะที่อยู่ใน readline จะขยายทั้งหมดที่ขยายได้ มีประโยชน์มาก อาจทุบตีจะมีการกำหนดค่าบางอย่างเพื่อผลเหมือนกัน? @Seth ฉันคิดว่านี่เป็น readline ในการทุบตีไม่ใช่ terminal emulator - ไม่แน่ใจว่า
Rmano

2
@Seth ไม่ทางลัดจาก Q ได้รับการจัดการโดยทุบตี คุณสามารถค้นหา'คำสั่งสำหรับจัดการประวัติ'ในman bash(ที่ใดที่บรรทัด 3030)
Radu Rădeanu

@ RaduRădeanuโอ้น่าสนใจ! ฉันไม่รู้ ฉันไม่ดีสำหรับสมมติฐานที่ไม่ดี
Seth

1
\e.และ\e_ถูกแมปกับฟังก์ชั่นที่ ReadLine yank-last-argและถูกแมปไป\e\C-y yank-nth-argน่าเศร้าที่ดูเหมือนว่าจะไม่มีคำสั่ง (เดียว) ที่เพิ่มอาร์กิวเมนต์ก่อนหน้าหลายรายการพร้อมกัน
Adaephon

คำตอบ:


5

หากคุณดูผลลัพธ์ของคำสั่งต่อไปนี้:

bind -l

หรือดีกว่าที่จะ:

bind -l | grep arg

คุณจะเห็นว่าไม่มีฟังก์ชัน readline ใด ๆ สำหรับอาร์กิวเมนต์ทั้งหมดเช่นyank-last-argสำหรับอาร์กิวเมนต์สุดท้าย - ซึ่งสามารถแทรกอาร์กิวเมนต์ล่าสุดไปยังคำสั่งก่อนหน้า (คำสุดท้ายของรายการประวัติก่อนหน้า) ดังนั้นหากไม่มีฟังก์ชั่นดังกล่าวส่วนใหญ่อาจไม่มีทางลัดในการบรรลุสิ่งที่คุณต้องการ

ลองสร้างลังเข้าใกล้คำขอของคุณ ...

ก่อนอื่นให้ดูตัวอย่างที่เอาต์พุตของคำสั่งต่อไปนี้:

bind -p | grep yank-nth-arg

ผลลัพธ์คือ:

"\e\C-y": yank-nth-arg

และสามารถแปลได้ดังนี้yank-nth-arg(ซึ่งแทรกอาร์กิวเมนต์แรกคำสั่งก่อนหน้า - มีอาร์กิวเมนต์ n แทรกอาร์กิวเมนต์ที่ n จากคำสั่งก่อนหน้านี้) ถูกผูกไว้กับAlt+ +Ctrly

ในทำนองเดียวกันสามารถตีความบรรทัดใด ๆ จากผลลัพธ์ของbind -pคำสั่ง

ตอนนี้ให้ความสนใจกับสถานการณ์ต่อไปนี้:

  • หากคุณตั้งค่าการเชื่อมโยงต่อไปนี้:

    bind '"\ea": "\e2\e."'

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

  • หากคุณตั้งค่า:

    bind '"\ea": "\e1\e. \e2\e."'

    หลังจากที่เมื่อคุณกดAlt+ Aที่สองคนแรกขัดแย้งของคำสั่งก่อนหน้าจะแทรกอยู่ในคำสั่งปัจจุบัน ถ้าจำนวนของการขัดแย้งจากคำสั่งก่อนหน้านี้คือไม่เกิน 2 ของหลักสูตรทั้งหมดของคำสั่งก่อนหน้าจะแทรกอยู่ในคำสั่งปัจจุบัน

  • หากคุณตั้งค่า:

    bind '"\ea": "\e1\e. \e2\e. \e3\e."'

    หลังจากที่เมื่อคุณกดAlt+ Aที่สามคนแรกขัดแย้งของคำสั่งก่อนหน้าจะแทรกอยู่ในคำสั่งปัจจุบัน ถ้าจำนวนของการขัดแย้งจากคำสั่งก่อนหน้านี้เป็นจำนวนสูงสุด 3 (เช่นในกรณีของคุณ) ของหลักสูตรทั้งหมดของคำสั่งก่อนหน้าจะแทรกอยู่ในคำสั่งปัจจุบัน

  • และอื่น ๆ

สำหรับ 10 อาร์กิวเมนต์แรกคุณสามารถใช้:

bind '"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."'

และฉันคิดว่านี่นานพอที่ฉันจะไม่ใช้คำสั่งที่มักจะมีข้อโต้แย้งมากมาย

ในการทำให้ถาวรให้เพิ่มบรรทัดบรรทัดต่อไปนี้ใน~/.inputrcไฟล์ของคุณ:

"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."

ในตัวอย่างนี้ฉันเลือกAlt+ Aเพื่อแทรกอาร์กิวเมนต์ทั้งหมด (ถ้าจำนวนอาร์กิวเมนต์ไม่มากกว่า 10) ของคำสั่งก่อนหน้า แต่คุณสามารถเลือกชุดค่าผสมอื่น ๆ ที่คุณใช้ด้วยการแทนที่\eaสตริงคำสั่งก่อนหน้า

แหล่งข้อมูล:


มันค่อนข้างแฮ็คและมันจะใช้ได้กับข้อโต้แย้งจำนวน จำกัด เท่านั้น แต่ดูเหมือนว่าจะใกล้เคียงที่สุดที่เราจะหาได้ง่าย - ฉันจะรับมัน;) จริงๆแล้วฉันเพิ่งดูซอร์สโค้ดของ readline ได้อย่างรวดเร็วก่อนที่ดูเหมือนว่าในไฟล์funmap.cฟังก์ชันyank-nth-argถูกแมปไปฟังก์ชัน C ซึ่งจะถูกกำหนดไว้ในrl_yank_nth_arg kill.canalogously yank-last-argสำหรับ แน่นอนว่ามันเป็นไปได้ที่จะขยาย readline ด้วยฟังก์ชันการทำงานดังกล่าว แต่ฉันไม่ต้องการทำเช่นนั้น ฉันชอบที่ ReadLine ของฉันที่จะได้รับการจัดการโดยaptและคุณลักษณะนี้ไม่ได้ที่สำคัญ;)
Malte Skoruppa
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.