ประวัติการทุบตีนั้นทรงพลังมาก การทำความเข้าใจวิธีใช้การขยายประวัติทุบตีอย่างมีประสิทธิภาพจะทำให้คุณทำงานได้อย่างมีประสิทธิภาพบนบรรทัดคำสั่ง Linux
บทความนี้อธิบาย 15 ตัวอย่างที่ใช้คุณลักษณะการขยายประวัติทุบตีต่อไปนี้:
- ตัวกำหนดเหตุการณ์ – หมายถึงคำสั่งเฉพาะในประวัติศาสตร์ มันเริ่มต้นด้วย !
- ตัวกำหนดคำ – หมายถึงคำเฉพาะของรายการประวัติ โดยปกติสิ่งนี้จะรวมกับตัวกำหนดคู่ แม้แต่ผู้กำหนดและตัวกำหนดคำก็ยังคั่นด้วยเครื่องหมายทวิภาค
- ตัวแก้ไข – แก้ไขผลลัพธ์ของการแทนที่ที่ทำโดยเหตุการณ์หรือตัวกำหนดคำ
บทความนี้เป็นส่วนหนึ่งของ Bash Tutorial Series ที่กำลังดำเนินการอยู่
ดังที่คุณทราบแล้ว หากต้องการดูรายการประวัติทั้งหมด ให้ใช้คำสั่ง history ซึ่งจะแสดงคำสั่งทั้งหมดที่ดำเนินการก่อนหน้านี้พร้อมกับตัวเลขสำหรับคำสั่งนั้นในตารางประวัติ
$ history 1 tar cvf etc.tar /etc/ 2 cp /etc/passwd /backup 3 ps -ef | grep http 4 service sshd restart 5 /usr/local/apache2/bin/apachectl restart
ตัวกำหนดเหตุการณ์ประวัติการทุบตี
1. ดำเนินการคำสั่งเฉพาะจากประวัติโดยใช้ !n
หากคุณได้ดำเนินการคำสั่งก่อนหน้านี้ แทนที่จะพิมพ์ใหม่อีกครั้ง คุณสามารถดำเนินการได้อย่างรวดเร็วโดยใช้หมายเลขที่เกี่ยวข้องของคำสั่งในประวัติ
ตัวอย่างเช่น ในการรันคำสั่ง #4 ให้ทำดังต่อไปนี้ ซึ่งจะแสดงคำสั่ง #4 จากประวัติและดำเนินการทันที
$ !4 service sshd restart
ในการรันคำสั่งที่พิมพ์ 2 คำสั่งกลับ ให้ทำดังต่อไปนี้
$ !-2
ในการรันคำสั่งก่อนหน้า ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้:
$ !! $ !-1
คุณยังสามารถกด
หากคุณเปิดใช้งานการแก้ไขสไตล์ vi สำหรับบรรทัดคำสั่งโดยใช้ 'set -o vi' ให้ใช้
2. ดำเนินการคำสั่งด้วยคำหลักโดยใช้ !string และ !?string
คุณยังสามารถใช้คีย์เวิร์ดเพื่อรันคำสั่งจากประวัติได้อีกด้วย
ตัวอย่างต่อไปนี้จะค้นหาคำสั่งก่อนหน้าที่ เริ่มต้นด้วยคำหลัก “ps” และดำเนินการ ในตัวอย่างนี้ จะเลือกคำสั่งก่อนหน้า “ps -ef | grep http” และดำเนินการ
$ !ps ps -ef | grep http
ตัวอย่างต่อไปนี้จะค้นหาคำสั่งก่อนหน้าที่ มีคำหลัก “apache” และดำเนินการ ในตัวอย่างนี้ จะเลือกคำสั่งก่อนหน้า “/usr/local/apache2/bin/apachectl restart” และดำเนินการดังกล่าว
$ !?apache /usr/local/apache2/bin/apachectl restart
3. แทนที่สตริงจากคำสั่งก่อนหน้าโดยใช้ ^str1^str2^
ในตัวอย่างต่อไปนี้ ขั้นแรก เรารันคำสั่ง ls เพื่อตรวจสอบไฟล์ ต่อมาเราตระหนักว่าเราต้องการดูเนื้อหาของไฟล์ แทนที่จะพิมพ์ชื่อไฟล์ทั้งหมดอีกครั้ง เราสามารถแทนที่ “ls” ในคำสั่งก่อนหน้าด้วย “cat” ดังที่แสดงด้านล่าง
$ ls /etc/cron.daily/logrotate $ ^ls^cat^ cat /etc/cron.daily/logrotate
หมายเหตุ:สำหรับเคล็ดลับเพิ่มเติมเกี่ยวกับประวัติทุบตี ให้อ้างอิง 15 ตัวอย่างสำหรับประวัติบรรทัดคำสั่ง Linux ระดับมาสเตอร์ ซึ่งจะอธิบายวิธีแสดงการประทับเวลาในประวัติ และวิธีใช้ตัวแปรสภาพแวดล้อมที่เกี่ยวข้องกับประวัติต่างๆ รวมถึง HISTTIMEFORMAT, HISTSIZE, HISTFILE, HISTCONTROL และ HISTIGNORE
ตัวกำหนดคำประวัติทุบตี
ตัวกำหนดคำมีประโยชน์มากเมื่อคุณต้องการพิมพ์คำสั่งใหม่ แต่ใช้อาร์กิวเมนต์จากคำสั่งใดคำสั่งหนึ่งที่ดำเนินการก่อนหน้านี้ ตัวอย่างบางส่วนแสดงไว้ด้านล่าง
4. รับอาร์กิวเมนต์ที่ 1 ของคำสั่งโดยใช้ :^
ในตัวอย่างต่อไปนี้ “!cp:^” ถูกกำหนดให้เป็นอาร์กิวเมนต์ของคำสั่ง “ls -l” “!cp:^” ค้นหาคำสั่งก่อนหน้าในประวัติที่ขึ้นต้นด้วย “cp” และรับอาร์กิวเมนต์ที่ 1 ของคำสั่งนั้น
$ cp /etc/passwd /backup $ ls -l !cp:^ ls -l /etc/passwd
ตัวอย่างต่อไปนี้รับอาร์กิวเมนต์ที่ 1 จากคำสั่งก่อนหน้า
$ ls -l !!:^
5. รับอาร์กิวเมนต์สุดท้ายของคำสั่งโดยใช้ :$
ในตัวอย่างต่อไปนี้ “!cp:$” ถูกกำหนดให้เป็นอาร์กิวเมนต์ของคำสั่ง “ls -l” “!cp:$” ค้นหาคำสั่งก่อนหน้าในประวัติที่ขึ้นต้นด้วย “cp” และรับอาร์กิวเมนต์สุดท้ายของคำสั่งนั้น
$ cp /etc/passwd /backup $ ls -l !cp:$ ls -l /backup
ตัวอย่างต่อไปนี้รับอาร์กิวเมนต์สุดท้ายจากคำสั่งก่อนหน้า
$ls -l !!:$
6. รับอาร์กิวเมนต์ที่ n ของคำสั่งโดยใช้ :n
ในตัวอย่างต่อไปนี้ ให้ “!tar:2” เป็นอาร์กิวเมนต์ของคำสั่ง “ls -l” “!tar:2” ค้นหาคำสั่งก่อนหน้าในประวัติที่ขึ้นต้นด้วย “tar” และรับอาร์กิวเมนต์ที่ 2 ของคำสั่งนั้น
$ tar cvfz /backup/home-dir-backup.tar.gz /home $ ls -l !tar:2 ls -l /backup/home-dir-backup.tar.gz
7. รับอาร์กิวเมนต์ทั้งหมดจากคำสั่งโดยใช้ :*
ในตัวอย่างต่อไปนี้ “!cp:*” ถูกกำหนดให้เป็นอาร์กิวเมนต์ของคำสั่ง “ls -l” “!cp:*” ค้นหาคำสั่งก่อนหน้าในประวัติที่ขึ้นต้นด้วย “cp” และรับอาร์กิวเมนต์ทั้งหมด
$ cp /etc/passwd /backup $ ls -l !cp:* ls -l /etc/passwd /backup
8. อ้างถึงคำที่ค้นหาล่าสุดโดยใช้ !%
ดังที่เราได้อธิบายไว้ข้างต้น “!?apache” จะค้นหาคำสั่งประวัติก่อนหน้าที่มีคำหลัก “apache” และดำเนินการดังกล่าว
$ /usr/local/apache2/bin/apachectl restart $ !?apache /usr/local/apache2/bin/apachectl restart
!% จะหมายถึงทั้งคำที่ตรงกับก่อนหน้านี้ “?” ค้นหา.
ตัวอย่างเช่น หากคุณเคยค้นหาคำว่า “?apache” มาก่อน “!%” จะจับคู่ทั้งคำ “/usr/local/apache2/bin/apachectl” โปรดทราบว่า “/” จะถือว่าเป็นส่วนหนึ่งของคำเดียวในบริบทนี้
ดังนั้น ในกรณีนี้ คุณสามารถหยุด Apache ได้โดยดำเนินการดังต่อไปนี้
$ !% stop /usr/local/apache2/bin/apachectl stop
9. รับช่วงอาร์กิวเมนต์จากคำสั่งโดยใช้ x-y
ในตัวอย่างต่อไปนี้ “!tar:3-5” ถูกกำหนดเป็นอาร์กิวเมนต์ของคำสั่ง “ls -l” “!tar:3-5” ค้นหาคำสั่งก่อนหน้าในประวัติที่ขึ้นต้นด้วย “tar” และรับอาร์กิวเมนต์ตั้งแต่ 3 ถึง 5
$ tar cvf home-dir.tar john jason ramesh rita $ ls -l !tar:3-5 ls -l john jason ramesh
ต่อไปนี้รับอาร์กิวเมนต์ทั้งหมดจาก 2
$ ls -l !tar:2-$
โปรดทราบสิ่งต่อไปนี้:
- !!:* รับอาร์กิวเมนต์ทั้งหมดจากคำสั่งก่อนหน้า
- !!:2* รับอาร์กิวเมนต์ทั้งหมดโดยเริ่มจากอาร์กิวเมนต์ที่ 2
- !!:2-$ เหมือนข้างบน รับอาร์กิวเมนต์ทั้งหมดโดยเริ่มจากอาร์กิวเมนต์ที่ 2
- !!:2- รับอาร์กิวเมนต์ทั้งหมดที่เริ่มต้นจากอาร์กิวเมนต์ที่ 2 (ยกเว้นอาร์กิวเมนต์สุดท้าย)
ตัวดัดแปลงประวัติการทุบตี
Modifer จะได้รับตามหลังคำว่า designators ดังที่อธิบายไว้ในตัวอย่างด้านล่าง
10. ลบชื่อเส้นทางต่อท้ายออกจากคำโดยใช้ :h
ในตัวอย่างต่อไปนี้ “!!:$:h” รับอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้า และลบชื่อพาธต่อท้าย ในกรณีนี้ จะลบชื่อไฟล์และรับเฉพาะเส้นทางแบบเต็ม
$ ls -l /very/long/path/name/file-name.txt $ ls -l !!:$:h ls -l /very/long/path/name
11. ลบชื่อพาธนำทั้งหมดออกจากคำโดยใช้ :t
ซึ่งตรงกันข้ามกับตัวอย่างก่อนหน้านี้ทุกประการ
ในตัวอย่างต่อไปนี้ “!!:$:t” รับอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้า และลบชื่อพาธชั้นนำทั้งหมด ในกรณีนี้จะได้เฉพาะชื่อไฟล์
$ ls -l /very/long/path/name/file-name.txt $ ls -l !!:$:t ls -l file-name.txt
12. ลบนามสกุลไฟล์ออกจากคำโดยใช้ :r
ในตัวอย่างต่อไปนี้ “!!:$:r” รับอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้า และลบเฉพาะ “.suffix” (ซึ่งเป็นนามสกุลไฟล์ที่นี่) ในกรณีนี้ จะเป็นการลบ .txt
$ ls -l /very/long/path/name/file-name.txt $ ls -l !!:$:r ls -l /very/long/path/name/file-name
13. Sed like Substitution ในประวัติทุบตีโดยใช้ :s/str1/str2/
แทนที่จะใช้ “^original^replacement^” ตามที่เราได้กล่าวไว้ก่อนหน้านี้ เรายังสามารถใช้ sed like substitution ในประวัติทุบตีดังที่แสดงในตัวอย่างด้านล่าง นี่อาจจะจำง่าย !! คือการเรียกคำสั่งก่อนหน้า “:s/original-string/replacement-string/” เป็น sed-like syntax เพื่อแทนที่สตริง
$ !!:s/ls -l/cat/
คุณยังสามารถใช้แฟล็ก g (พร้อมกับแฟล็ก s) เพื่อทำการแทนที่โกลบอลดังที่แสดงด้านล่าง สิ่งนี้มีประโยชน์เมื่อคุณพิมพ์ผิดหลายคำและต้องการเปลี่ยนแปลงคำทั้งหมดพร้อมกันและดำเนินการคำสั่งอีกครั้ง
ในตัวอย่างต่อไปนี้ ฉันให้ "รหัสผ่าน" สองครั้งโดยไม่ได้ตั้งใจ (แทนที่จะเป็นรหัสผ่าน)
$ cp /etc/password /backup/password.bak
ในการแก้ไขปัญหานี้ ให้ทำดังนี้ ประวัติศาสตร์โลก sed like substitution
$ !!:gs/password/passwd/ cp /etc/passwd /backup/passwd.bak
14. ทำซ้ำการแทนที่อย่างรวดเร็วโดยใช้ :&
หากคุณดำเนินการแทนที่ประวัติ bash สำเร็จแล้วดังที่แสดงด้านบน คุณสามารถทำซ้ำการแทนที่เดิมอย่างรวดเร็วอีกครั้งโดยใช้ :&
ฉันพิมพ์คำว่า "รหัสผ่าน" ผิดอีกครั้งแทนที่จะเป็น "passwd" ในคำสั่งอื่น
$ tar cvf password.tar /etc/password
ตอนนี้ แทนที่จะพิมพ์คำสั่งใหม่ หรือทำ "gs/password/passwd" ฉันสามารถใช้ ":&" ซึ่งจะใช้การแทนที่ครั้งล่าสุดซ้ำได้ ใช้ “:g&” เพื่อนำการแทนที่สุดท้ายมาใช้ซ้ำทั่วโลก
$ !!:g& tar cvf passwd.tar /etc/passwd
15. พิมพ์คำสั่งโดยไม่ต้องดำเนินการโดยใช้ :p
สิ่งนี้มีประโยชน์มากเมื่อคุณทำการแทนที่ประวัติที่ซับซ้อน และคุณต้องการดูคำสั่งสุดท้ายก่อนที่จะดำเนินการ
ในตัวอย่างต่อไปนี้ “!tar:3-:p” ไม่ได้รันคำสั่งจริงๆ
เนื่องจากเราได้ให้ “:p” ที่นี่ มันแค่ทำการแทนที่และแสดงคำสั่งใหม่ เมื่อคุณตรวจสอบการขยายประวัติทุบตีแล้ว และหากคุณคิดว่านี่เป็นคำสั่งที่คุณต้องการเรียกใช้ ให้ลบ “:p” แล้วดำเนินการอีกครั้ง
$ tar cvf home-dir.tar john jason ramesh rita $ tar cvfz new-file.tar !tar:3-:p tar cvfz new-file.tar john jason ramesh