จะเลิกทำการเปลี่ยนแปลงใน command-history ได้อย่างไร?


12

ในระบบ UNIX คุณสามารถกดลูกศรบนและล่างเพื่อเลื่อนดูคำสั่งก่อนหน้า มันมีประโยชน์มาก

บางครั้งฉันก็ขึ้นไปและพบคำสั่งที่ฉันต้องการใช้อีกครั้ง แต่มีรูปแบบบางอย่าง historyถ้าฉันจะเปลี่ยนแปลงดังกล่าวแล้วผมไม่ได้มีวิธีการที่จะได้รับกลับคำสั่งเดิมจนกว่าฉันตรวจสอบใน

มีวิธีใดบ้างที่จะ "เลิกทำ" การเปลี่ยนแปลงคำสั่งในประวัติการเข้าใช้ผ่านทางคีย์?

วิธีแก้ปัญหาปัจจุบันของฉันคือการผนวก#คำสั่ง วิธีนี้ดำเนินการคำสั่งปัจจุบันเป็นความคิดเห็นจึงไม่มีอะไรเกิดขึ้น จากนั้นฉันสามารถเรียกดูอีกครั้งผ่านคำสั่งด้วยปุ่มต่างๆ ปัญหาคือว่าคำสั่งที่ฉันใช้อาจจะเป็นรายการที่อยู่ห่างไกลในรายการดังนั้นการขึ้นอีกสองร้อยครั้งนั้นค่อนข้างน้อย Control + R ไม่ใช่วิธีแก้ปัญหาอย่างใดอย่างหนึ่งเนื่องจากฉันอาจจำไม่ได้ว่าสิ่งที่ฉันกำลังมองหา

ตัวอย่าง

ฉันพิมพ์ "50 คำสั่งที่ผ่านมา" ต่อไปนี้:

ls -l /etc/httpd/conf/

ตอนนี้ฉันขึ้นไปที่บรรทัดนั้นและเปลี่ยนเป็น

ls -l /etc/init.d/

แต่ไม่ได้กด Enter ตอนนี้ฉันต้องการไปที่ls -l /etc/httpd/conf/อีกครั้ง

สภาพแวดล้อมของฉัน

$ echo $SHELL
/bin/bash
$ echo $TERM
xterm

ว่าประวัติคำสั่งมีการเปลี่ยนแปลงน่าจะเป็นคุณสมบัติ (mis-) ของเชลล์ที่คุณใช้ ในkshตัวอย่างเช่นคุณสามารถแก้ไขรายการประวัติและเรียกใช้โดยไม่ต้องลบ "เวอร์ชันก่อนหน้า" ของรายการ คุณมีคำสั่งที่เรียกใช้ทั้งหมด
Janis

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

1
นอกจากนี้ในกรณีนี้kshพฤติกรรมของแตกต่างกันที่นี่ดูเหมือน และตัวเลือกการแก้ไขประวัติของคุณยังขึ้นอยู่กับโหมดการแก้ไขที่เลือก ในksh's vi โหมดเช่นรายการเก่าไม่ถูกเขียนทับและฉันยังสามารถออกคำสั่งยกเลิกเหมือนในviกับ 'U'
Janis

อืมฟังดูมีแนวโน้มมาก ตอนนี้ฉันทำงานใน Bash และไม่ได้พิจารณาที่จะเปลี่ยนkshแต่ก็ดีที่จะรู้ว่ามีสิ่งนั้นอยู่ที่นั่น
fedorqui

ฉันต้องการทราบว่า bash เก็บประวัติคำสั่งล่าสุดก่อนที่จะเขียนไปยังไฟล์ประวัติเมื่อเชลล์ปิด มันอาจช่วยในการพิจารณาว่าเป็นไปได้ ใคร? ฉันคิดว่ามันอาจเป็นหนึ่งในตัวแปรเชลล์ แต่ไม่มีเวลาที่จะอ่านคู่มือ
iyrin

คำตอบ:


10

ตราบใดที่คุณแก้ไขรายการประวัติ แต่ยังไม่กดEnterเพื่อกลับไปที่รายการเดิมให้กดCtrl+ _- undoคำสั่ง - ซ้ำ ๆจนกว่าจะไม่มีการเปลี่ยนแปลงใด ๆ เพิ่มเติม คุณกลับไปที่รายการเดิม


5

เปลี่ยนกลับเป็นคำสั่งเดิมเมื่อคุณทำการเปลี่ยนแปลงหลายบรรทัด:

revert-line (M-r) 
    Undo all changes made to this line. This is like 
executing the undo command enough times to get back to the beginning.

Mคือเมตาคีย์ซึ่งaltrสำหรับฉัน


ยังไม่ได้ข้อมูลที่เป็นประโยชน์

เมื่อคุณได้ดำเนินการคำสั่งเช่น OP เคยทำมาก่อนหน้านี้ (มันเกิดขึ้น) มีอะไรที่จะ "เลิก" เพราะคำสั่งที่ได้รับการจัดการและจำโดยGNU Readlineห้องสมุดและไม่ได้เขียนเพื่อ$HISTFILEจนกว่าจะออกจากเปลือก เหตุผลที่ผมกล่าวถึงนี้เป็นเพราะคุณไม่สามารถเพียงแค่เหมือนหนึ่งอาจคาดหวังและมันอาจจะไม่เหมาะที่จะออกจากเปลือกgrep$HISTFILE

ดังนั้นนี่คือตัวเลือกสองตัวที่จะช่วยคุณไม่ให้เลื่อนกลับไปที่คำสั่ง readline ก่อนหน้าทั้งหมด

หากคุณจำคำสั่งบางคำได้ให้กดctrl+ rและพิมพ์สิ่งที่คุณจำเพื่อค้นหาคำสั่งก่อนหน้าซึ่งมีสตริงนั้น การกดctrl + rอีกครั้งจะแสดงครั้งต่อไปล่าสุดค้นหาย้อนหลัง

ตัวอย่างเช่นพิมพ์ls -lแล้วctrl+ rหลาย ๆ ครั้งเพื่อค้นหาคำสั่งก่อนหน้าที่คุณค้นหา หากคุณเลื่อนดูผ่านctrl+sจะค้นหาไปข้างหน้าจากตำแหน่งปัจจุบัน

fcคำสั่งทุบตีในตัวจะเป็นประโยชน์ที่จะแสดงรายการตัวเลขดัชนีควบคู่ไปกับคำสั่งที่ ReadLine ก่อนหน้านี้

fc -l -100 จะแสดงรายการ 100 คำสั่งก่อนหน้าใน readline

นอกจากนี้หาก OP รู้ว่าเขากำลังมองหาls -lคำสั่งก่อนหน้าเขาสามารถไพพ์เอาต์พุตgrepเช่น:fc -l -100 | grep 'ls -l'

นี่ควรแสดงรายการls -lคำสั่งก่อนหน้านี้ที่นำหน้าด้วยหมายเลขดัชนี ผลลัพธ์มีลักษณะดังนี้:
2065 ls -l

ตอนนี้คุณสามารถใช้ตัวกำหนดเหตุการณ์!nซึ่งnเป็นหมายเลขดัชนีได้ ในตัวอย่างนี้การดำเนินการจะขยายไปยัง!2065ls -l


แม้ว่าจะไม่ได้ช่วยอะไรจริงใครก็ตามที่ต้องการเก็บประวัติคำสั่งล่าสุดเมื่อแก้ไขคำสั่งก่อนหน้านี้ควรดูHISTORY EXPANSIONส่วนของman bashส่วนหนึ่งของต่อไปนี้เป็นวิธีการทางเลือกอื่นสำหรับการแก้ไขคำสั่งเก่าโดยไม่เขียนทับประวัติ

Event Designatorsส่วนที่แสดงให้เห็นวิธีการที่คุณสามารถแก้ไขสตริงจากคำสั่งที่ใช้มากที่สุดเมื่อเร็ว ๆ นี้

^string1^string2^
              Quick  substitution.  Repeat the previous command, replacing string1 with string2.  Equivalent to
              ``!!:s/string1/string2/'' (see Modifiers below).

ตัวอย่าง:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar

คำสั่งล่าสุดจะแสดง:

echo foo
echo bar

ตัวอย่างข้างต้นยังอธิบายถึงวิธีการใช้sedเพื่อแทนที่สตริงในตัวออกแบบเหตุการณ์

!-n    Refer to the current command minus n.

ดังนั้นหาก 3 คำสั่งในประวัติศาสตร์เป็นเช่นecho fooนั้นคุณจะใช้:
!-3:s/foo/bar

โปรดทราบว่าผู้ออกแบบเหตุการณ์จะปรากฏในประวัติของคุณเมื่อคำสั่งดำเนินการในกรณีecho barนี้ !-3:s/foo/barมันจะไม่ปรากฏในประวัติศาสตร์เป็น

เพียงแค่โยนมันออกไปเพราะดูเหมือนว่าจะมีความสัมพันธ์กันอย่างใกล้ชิดแม้ว่าจะเป็นมากกว่า "ไม่ต้องทำ" มากกว่าวิธีการแก้ปัญหา "เลิกทำ" OP กำลังมองหา


นี่เป็นสิ่งที่ดีขอบคุณมากสำหรับข้อมูลรายละเอียด ฉันยอมรับคำตอบของ Gilles เพราะทำในสิ่งที่ฉันกำลังมองหาในขณะที่คุณคิดว่าฉันรู้หลายสิ่งเกี่ยวกับคำสั่งที่ฉันต้องการทำซ้ำซึ่งไม่ได้เป็นอย่างนั้นเสมอไป
fedorqui

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