grep สำหรับเส้นที่ไม่อยู่หลังรูปแบบ
ฉันกำลังพยายามค้นหาทุกบรรทัดของไฟล์ที่ไม่ได้อยู่หลังรูปแบบเฉพาะ
ในบางครั้งฉันมีปัญหากับการhistory
ใช้ GNU bash
(เวอร์ชัน 4 และ 5) ซึ่งคำสั่งปรากฏในรายการที่ซ้ำกัน ฉันคิดว่านี่เป็นเพราะความจริงที่ว่าใน.bashrc
ฉันมีบรรทัดต่อไปนี้:
PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"
และเนื่องจากฉันใช้เทอร์มินัลมัลติเพล็กเซอร์ ( screen
และ / หรือtmux
) คำสั่งที่กล่าวถึงข้างต้นจึงถูกดำเนินการหลายครั้ง (ดังนั้นecho $PROMPT_COMMAND
ผลลัพธ์คือhistory -a; history -n; history -a; history -n;
ในบางสถานการณ์ (โดยเฉพาะอย่างยิ่งเมื่อทำสิ่งต่างๆร่วมกันบนบานหน้าต่าง / หน้าต่าง / เฟรม / บัฟเฟอร์ที่แตกต่างกัน) คำสั่งสุดท้ายที่ฉันป้อนจะถูกเก็บไว้สองครั้งหรือบ่อยกว่านั้นใน~/.bash_history
ไฟล์. สิ่งนี้นำไปสู่รายการดังต่อไปนี้:
#1596110297
yadm list -a | xargs -t ls -l
yadm list -a | xargs -t ls -l
ไม่จำเป็นต้องพูดว่ามันค่อนข้างน่ารำคาญ ฉัน (หวังว่า) พบการแก้ไขสำหรับ การแก้ไข: สิ่งนี้ไม่ได้ช่วยแก้ปัญหาเกี่ยวกับรายการที่ซ้ำกันในไฟล์history
-issue (โดยเปลี่ยนคำสั่งเป็นPROMPT_COMMAND="history -a; history -n
) แต่history
.
ตอนนี้ฉันต้องการกำจัดรายการที่ซ้ำกัน
ดังนั้นฉันกำลังพยายามหานิพจน์ทั่วไปเพื่อทำเครื่องหมายทุกอย่างยกเว้นบรรทัดที่ขึ้นต้นด้วย#
และอีกหนึ่งบรรทัดหลังจากนั้น ความคิดแรกของฉันคือการรวมกันgrep -v
(เพื่อกลับรายการที่เลือก) และgrep -A 1
(เพื่อให้ได้หนึ่งบรรทัดเพิ่มเติมหลังจากรูปแบบการจับคู่) แต่
grep -v "^#" -A 1 ~/.bash_history
ไม่ได้ผลลัพธ์ที่ฉันหวังไว้
ดังนั้นคำถามของฉัน: ใครมีความคิดที่ดีเกี่ยวกับวิธีการใช้grep
? ถ้าไม่ได้: วิธีการที่ฉันสามารถบรรลุนี้กับเครื่องมืออื่น ๆ ( sed
, awk
, ... )?
คำตอบ
เท่าที่ฉันเข้าใจgrep -v "^#" -A 1
หมายถึงการพิมพ์บรรทัดที่ไม่ได้ขึ้นต้นด้วยเครื่องหมายแฮและหนึ่งบรรทัดต่อจากแต่ละบรรทัด แต่คุณไม่ต้องการตรงข้ามพิมพ์บรรทัดที่จะเริ่มต้นด้วยเครื่องหมายกัญชาและหนึ่งบรรทัดหลัง?
ให้ไฟล์ทดสอบ:
#123
echo this
echo this
#456
echo that
echo that
echo that
#789
echo third
grep -A1 ^# history.txt |grep -vxFe --
พิมพ์:
#123
echo this
#456
echo that
#789
echo third
ประการที่สองgrep
คือการกำจัดการgrep -A
พิมพ์ตัวคั่นกลุ่ม
หรืออีกวิธีหนึ่งuniq history.txt
ควรพิมพ์บรรทัดที่เหมือนกันเพียงชุดเดียว
ใช้ Raku (née Perl6)
ดูเหมือนจะเป็นงานสำหรับโอเปอเรเตอร์ "flip-flop" ซึ่งมีให้บริการในภาษาสคริปต์หลายภาษา ด้านล่างนี้เป็นคำตอบโดยใช้ภาษาโปรแกรม Raku (ก่อนหน้านี้เรียกว่า Perl6) เริ่มต้นด้วยการสร้างไฟล์ทดสอบที่ครอบคลุมมากขึ้น:
$ cat repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
B_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
D_yadm list -a | xargs -t ls -l
E_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
G_yadm list -a | xargs -t ls -l
H_yadm list -a | xargs -t ls -l
I_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
ตอนนี้สำหรับซับเดียวโดยใช้fff
โอเปอเรเตอร์ฟลิปฟล็อปของ Raku ซึ่งใช้พฤติกรรมที่ "เหมือน sed" การจับจะเปิดสำหรับบรรทัดที่ regex แรกเห็น (ที่จุดเริ่มต้นของบรรทัด^^
) อักขระ "#" ตามตัวอักษร เมื่อเปิดแล้วการจับจะไม่สนใจ regex แรกและจะประเมินเทียบกับ regex ที่สองโดยจะปิดเมื่อพบว่าตรงกับบรรทัดที่ขาดหายไป (ที่จุดเริ่มต้นของบรรทัด^^
) เป็นอักขระ "#" regex 'negative' ถูกนำไปใช้ในโค้ดด้านล่างโดยใช้<-[#]>
ซึ่งเป็น "Enumerated Character Class" เชิงลบและคุณลักษณะที่แท้จริงของภาษา Raku:
$ raku -ne '.put if /^^ "#" / fff /^^ <-[#]> /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
อันที่จริงแล้ว regex แรก (ทางด้านซ้ายของตัวfff
ดำเนินการ infix) สามารถเขียนได้โดยใช้<+[#]>
ซึ่งเป็น "Enumerated Character Class" ที่เป็นบวกสำหรับการสร้างแบบขนานมากขึ้น:
$ raku -ne '.put if /^^ <+[#]> / fff /^^ <-[#]> /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
นอกจากนี้สำหรับฉันแล้วดูเหมือนว่าคุณสามารถปรับปรุง regex ของคุณได้โดยเรียกร้องให้มีการจับคู่หรือเทียบกับจุดเริ่มต้นของบรรทัด "#" ตามด้วยตัวเลขอย่างน้อยหนึ่งตัวเช่น<digit>+
ดูด้านล่าง:
$ raku -ne '.put if /^^ <+[#]> <digit>+ / fff /^^ <-[#]> <-digit>+ /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
[โค้ดด้านบนทั้งหมดจะลบบรรทัดที่ซ้ำกันที่ขึ้นต้นด้วย B, D, E, G, H และ I สิ่งที่แปลกประหลาดอย่างเดียวที่ฉันสังเกตเห็นคือเส้นเป้าหมายสองเส้นที่ต่อเนื่องกันเช่น "# 1596110297" จะปรากฏในผลลัพธ์ของคุณ แต่ก็ไม่ชัดเจน ให้ฉันถ้าไฟล์อินพุตของคุณจะมีบรรทัดต่อเนื่องกัน]