จะเปลี่ยนคำแรกในคำสั่ง Bash อย่างรวดเร็วได้อย่างไร?


44

ฉันต้องการปรับปรุงขั้นตอนการทำงานของฉันด้วย Bash และฉันรู้ว่าฉันมักจะต้องการรันคำสั่งเดียวกันกับโปรแกรมที่แตกต่างกัน

ตัวอย่างบางส่วน:

Git (ที่ฉันต้องการเปลี่ยนคำที่สองอย่างรวดเร็ว):

git diff     foo/bar.c
git checkout foo/bar.c

Cat / rm (โดยที่จะต้องเปลี่ยนเฉพาะคำแรกเท่านั้น):

cat foo/is/a/very/long/path/to/bar.c
rm  foo/is/a/very/long/path/to/bar.c

ฉันรู้ว่าฉันสามารถตีCtrl+ aแล้วDelจะลบคำแรก แต่ผมสงสัยว่าถ้ามีวิธีที่รวดเร็วที่จะทำมัน



สุจริตฉันคิดว่ามันปลอดภัยที่สุดที่จะเพียงแค่ใช้ Ctrl + a และลบ มันไม่ช้าอย่างแน่นอน
agweber

คำตอบ:


56

!$ ขยายเป็นคำสุดท้ายของคำสั่งก่อนหน้าของคุณ

ดังนั้นคุณสามารถทำได้:

cat foo/is/a/very/long/path/to/bar.c

rm !$

หรือ:

git diff foo/bar.c

git checkout !$

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

ดูส่วน "การขยายประวัติ" ของbashหน้าคน มีความยืดหยุ่นมากมาย


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

1
@Hastur คุณสามารถตั้งค่าเปลือกของคุณเพื่อขยายประวัติบนแท็บหรือเมื่อเข้าไปเพื่อป้องกันอุบัติเหตุ
slhck

2
@Hastur ว่าทำไมคุณต้องกดบทนำครั้งที่สองใน zsh (โปรโมชั่นไร้ยางอาย)
Braiam

@Hastur - เมื่อฉันมีข้อสงสัยเกี่ยวกับสิ่งที่จะเกิดขึ้นหรือฉันรู้ตัวว่าฉันต้องทำอย่างอื่นก่อนที่จะใช้บางสิ่งบางอย่างนานก่อนที่ฉันจะพิมพ์สิ่งที่ฉันเพิ่งพิมพ์ฉันจะไปที่จุดเริ่มต้นของบรรทัดและเพิ่ม#หรือecho เพื่อ ดูและมันจะเข้าสู่ประวัติศาสตร์เพื่อให้ฉันสามารถเรียกคืนและเรียกใช้อีกครั้งโดยไม่ต้องปิดใช้งานคำนำหน้า
โจ

28

Ctrl+ aเพื่อไปที่จุดเริ่มต้นของบรรทัดจากนั้นกดAlt+ dเพื่อลบคำแรก


9
ทางลัดการลบคำเป็นจริง Meta + d และ Meta มักจะแมปไปยัง Alt บนเครื่อง Linux บนแพลตฟอร์มที่ไม่เป็นเช่นนี้ทางเลือกในการรับ Meta modifier คือการใช้ Escape เป็นคำนำหน้า ดูen.wikipedia.org/wiki/Meta_key
Gustavo Giráldez

2
@ GustavoGiráldezหากคุณต้องการลึกกว่านั้นMeta+Dจะใช้ได้เฉพาะเมื่อemacsเปิดใช้งาน (ผ่านset -o emacsหรือโดยค่าเริ่มต้น) มันจะไม่ทำงานในโปรแกรมแก้ไขที่ด้อยกว่า - โหมดหรือหากemacsปิดการใช้งาน
TC1

ในเทอร์มินัลจำนวนมาก (เพราะนี่คือสิ่งที่เทอร์มินัลและไม่ใช่สิ่ง Bash) ปุ่มโฮมจะไปที่จุดเริ่มต้นของบรรทัด แล็ปท็อปจำนวนมากทำแผนที่ Fn + ซ้ายไปที่ปุ่มโฮม ในทำนองเดียวกันปุ่มวางสายมักจะไปยังจุดสิ้นสุดของบรรทัด ฉันยังไม่ได้ใช้โปรแกรมจำลองเทอร์มินัลที่ไม่รองรับปุ่มลัดเหล่านี้
Kat

1
@ ไมค์ในทางกลับกันC-aและM-dพิมพ์ได้เร็วกว่ามากหากมือของคุณอยู่ในตำแหน่งพิมพ์แล้ว
jjlin

@ ไมค์นี่คือสิ่งที่ทุบตี พิมพ์catและเปรียบเทียบสิ่งที่คุณได้รับเมื่อกดปุ่ม Home ( ^[[Hที่นี่) และเมื่อกด Ctrl + a ( ^A)
Jonas Schäfer

17

ฉันไม่แน่ใจว่ามันจะเร็วกว่าจริงหรือไม่ แต่ดูบทความนี้โดยเฉพาะอย่างยิ่งจุด # .3:

  1. แทนที่สตริงจากคำสั่งก่อนหน้าโดยใช้ ^ str1 ^ str2 ^

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

$ ls /etc/cron.daily/logrotate

$ ^ls^cat^
cat /etc/cron.daily/logrotate

15

Alt+.

หากคุณต้องการทำซ้ำส่วนสุดท้ายของหนึ่งในคำสั่งก่อนหน้านี้อย่างใดอย่างหนึ่งคุณสามารถใช้Alt+ .ที่จะวางอาร์กิวเมนต์สุดท้ายที่นำมาจากบรรทัดสุดท้ายของประวัติศาสตร์

หากกดมากกว่าหนึ่งครั้งจะแทนที่สิ่งที่เพิ่งวางด้วยอาร์กิวเมนต์สุดท้ายของบรรทัดก่อน ...

เช่นถ้าคำสั่งสุดท้าย 2 คำสั่งคือ:

cat foo/is/a/very/long/path/to/bar.c
pico foo/is/a/very/long/path/to/SomeWhereElse.c

ในเชลล์ฉันเขียนrmและฉันกดAlt+ .มันจะปรากฏขึ้น:

rm foo/is/a/very/long/path/to/SomeWhereElse.c

ถ้าฉันกดอีกครั้งAlt+ .มันจะปรากฏขึ้นแทน

rm foo/is/a/very/long/path/to/bar.c

และอื่น ๆ ...


ไม่แน่ใจว่าทำไม แต่สิ่งนี้ไม่ทำงานบนคอนโซล Mac ของฉัน
lulalala

ที่นี่มีแป้นพิมพ์ลัดที่ใช้งานbashได้ BTW คุณแน่ใจหรือไม่ว่าคุณใช้ bash เป็นเชลล์ ?
Hastur

1
ฉันเดาว่านี่เป็นสิ่งที่ Mac เมื่อฉันพิมพ์ที่ฉันได้รับ
lulalala


12

นอกจาก @jjlin ตอบแล้วคุณอาจสนใจโดยเคล็ดลับต่อไปนี้:

  • Ctrl+ wลบคำทางซ้ายของคุณ
  • Ctrl+ kลบจากเคอร์เซอร์ไปที่ท้ายบรรทัดคำสั่ง
  • Ctrl+ uลบจากเคอร์เซอร์ไปที่จุดเริ่มต้นของบรรทัดคำสั่ง
  • Alt+ bเลื่อนเคอร์เซอร์ไปหนึ่งคำย้อนหลัง
  • Alt+ fเลื่อนเคอร์เซอร์ไปข้างหน้าหนึ่งคำ
  • $_ มีอาร์กิวเมนต์สุดท้ายของบรรทัดคำสั่งก่อนหน้า

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งเหล่านี้ให้ค้นหาส่วน "ชื่อคำสั่ง Readline" ของbashmanpage

เช่น:

cat foo/is/a/very/long/path/to/bar.c
rm $_

นี่เป็นเคล็ดลับที่ดี แต่พวกเขาไม่ตอบคำถาม
slhck

@slhck IMHO เกิดขึ้นเนื่องจากชื่อคำถามไม่ตรงกับตัวอย่างที่กำหนด หากเรามุ่งเน้นไปที่ตัวอย่างเช่นที่ฉันทำชื่อเรื่องควรเป็น"วิธีการเปลี่ยนคำอย่างรวดเร็วในคำสั่ง bash?" . นี่คือเหตุผลที่คำตอบของฉันคือ "นอกเหนือจาก @jjlin" แต่ฉันเดาว่าคำถามนั้นควรมีการชี้แจง
maiki

OP ต้องการลบ (แลกเปลี่ยน) nคำแรกในคำสั่งเสมอn = 1ในตัวอย่างแรกและn = 2ในคำที่สอง คำตอบของ jjlin แสดงให้เห็นว่าจะลบคำแรกอย่างไร (และโดยการใช้ทางลัดใหม่ลบnคำให้มากที่สุด) คำตอบของคุณแสดงรายการปุ่มลัด Bash (ซึ่งมีประโยชน์จริง ๆ ) แต่ไม่มีวิธีใดที่จะลบnคำแรกได้อย่างมีประสิทธิภาพ
slhck

อืมอ่านอีกครั้ง$_พารามิเตอร์อาจใช้งานได้หากมีเพียงอาร์กิวเมนต์เดียวเท่านั้น (เช่นถ้าn = m - 1ที่ไหนmคือจำนวนอาร์กิวเมนต์ทั้งหมด) ส่วนที่เหลือของทางลัดไม่เกี่ยวข้องกับคำถามว่า
slhck

@slhck เพื่อประโยชน์ในการเถียงฉันได้อ่านตัวอย่างแรกเป็น"แทนคำว่า 2" :-)
maiki

8

หากคุณมีความเชี่ยวชาญใน vi คุณสามารถเปิดใช้งาน vi ผูกในทุบตี (หอยมากที่สุด?) set -o viโดยใช้คำสั่ง จากนั้นคุณสามารถใช้ปุ่ม vi ปกติเพื่อแก้ไขคำสั่งของคุณ ในตัวอย่างแรกของคุณคุณสามารถทำได้^wcwเพื่อลบ "diff" จากนั้นเปลี่ยนเป็นเช็คเอาต์

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


ฉันเรียน kornshell ดังนั้นset -o viฉันจึงมีชีวิตอยู่! ฉันยังทำสิ่งนี้ใน bash ของฉันด้วยเช่นกัน
bgStack15

bindkey -vสำหรับ zsh Esc 0 c w
user530873

6

มีหลายวิธีในการดูแลแมวตัวนี้!

เพื่อแทนที่สตริงเฉพาะ^old^new^extraจะใช้คำสั่งก่อนหน้าของคุณแทนที่oldด้วยและผนวกnew extraคุณอาจหยุดเร็วเท่าที่คุณต้องการ; เช่น^oldจะแทนที่oldด้วยสตริงว่างและผนวกสตริงว่าง (โดยหลักแล้วลบoldและไม่ทำอะไรมาก)

1. ^diff^checkout
2. ^cat^rm

ตัวแปรที่มีประโยชน์อย่างยิ่งของสิ่งนี้:

for i in `seq 1 10`; do echo something complicated; done
# inspect the output to see if it looks right
^echo

เพื่อแทนที่คำที่เฉพาะเจาะจงคุณสามารถใช้!m:n-pในการอ้างถึงคำพูดnผ่านpของคำสั่งm(ใช้ตัวเลขเชิงลบที่จะนับกลับมาจากคำสั่งปัจจุบัน) คุณสามารถละ-pส่วนเพื่ออ้างถึงคำเดียวและละเว้น:m-pส่วนเพื่ออ้างถึงคำสั่งทั้งหมด รูปแบบพิเศษ!!สำหรับ!-1, !$สำหรับคำพูดสุดท้ายของคำสั่งก่อนหน้านี้และ!*สำหรับการขัดแย้ง ( แต่คำ0) ของคำสั่งก่อนหน้าจะมีประโยชน์สวย

1. !!:0 checkout !!:2-
2. rm !*

ฉันมักจะใช้ทั้งสองอย่างนี้; zsh เป็นสิ่งที่ดีเป็นพิเศษที่นี่เนื่องจากแท็บการกดปุ่มจะขยายเนื้อหาที่เป็นความลับออกไปเพื่อให้แน่ใจว่าคุณได้รับมันอย่างถูกต้อง

นอกจากนี้ยังมีวิธีการมากมายในการแก้ไขบรรทัด อ่านข้อมูลบนการโยงคีย์ของเชลล์ของคุณ


-2

โปรแกรมเทอร์มินัลส่วนใหญ่รองรับ ...

  • กด<Up-Arrow>ตามที่ต้องการเพื่อแสดงบรรทัดคำสั่งก่อนหน้าหนึ่งบรรทัดจากประวัติ
    • กด<Down-Arrow>ตามความจำเป็นเพื่อเลื่อนไปข้างหน้าผ่านรายการประวัติ
  • กด<Left-Arrow>ตามต้องการเพื่อเลื่อนเคอร์เซอร์ไปที่ท้ายคำที่สอง
  • กด<Backspace>ตามต้องการเพื่อลบคำที่สอง
  • พิมพ์คำที่สองแทน
    • กด<Right-Arrow>/ <Left-Arrow>ตามที่จำเป็นเพื่อเปลี่ยนตำแหน่งการเปลี่ยนแปลงเพิ่มเติม
  • กด<RETURN>ปุ่มเพื่อรันคำสั่ง

หากบรรทัดคำสั่งที่คุณต้องการไม่ใช่ล่าสุดให้ทำ reverse-i-search <Ctrl-r>ตามที่อธิบายในคำถาม ...
มีวิธีใช้ ctrl-r หลังจากพิมพ์ส่วนหนึ่งของคำสั่งใน bash หรือไม่?
จากนั้นแก้ไขผ่านปุ่มลูกศรตามต้องการ


-3

สิ่งที่ฉันทำ (Ubuntu / bash):

1) Arrow upเฮ้จะกลับคำสั่งก่อนหน้า
2) Homeกุญแจเพื่อกลับไปที่จุดเริ่มต้น
3) แก้ไขคำสั่งตามต้องการ

คนงี่เง่าพิสูจน์และมีประโยชน์อย่างยิ่งสำหรับคำสั่งหลายบรรทัด

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