การค้นหาแบบคำนึงถึงขนาดตัวพิมพ์ใน awk


20

ฉันต้องการค้นหาคำหลักที่ใช้ awk แต่ฉันต้องการทำการค้นหาแบบตรงตามตัวพิมพ์ใหญ่ - เล็ก (ไม่ต้องตรงตามตัวพิมพ์ใหญ่ - เล็ก)

ฉันคิดว่าวิธีที่ดีที่สุดคือการใช้ทั้งคำค้นหา ("คำสำคัญ") และบรรทัดเป้าหมายที่ awk อ่านพร้อมกัน จากคำถามนี้ฉันจะใช้toupperพิมพ์เป็นตัวพิมพ์ใหญ่ทั้งหมดได้อย่างไร แต่ฉันไม่รู้วิธีใช้ในการจับคู่เพราะคำตอบนั้นแสดงการพิมพ์และไม่ปล่อยให้ตัวพิมพ์ใหญ่เป็นตัวแปร

นี่คือตัวอย่างที่ได้รับข้อมูลนี้:

blablabla    
&&&Key Word&&&
I want all 
these text and numbers 123
and chars !"£$%&
as output
&&&KEY WORD&&&
blablabla

ฉันต้องการผลลัพธ์นี้:

I want all 
these text and numbers 123
and chars !"£$%&
as output

นี่คือสิ่งที่ฉันมี แต่ฉันไม่รู้วิธีเพิ่มในtoupper:

awk "BEGIN {p=0}; /&&&key word&&&/ { p = ! p ; next } ; p { print }" text.txt

คำตอบ:


23

แทนที่นิพจน์ของคุณเพื่อจับคู่รูปแบบ (เช่น/&&&key word&&&/) ด้วยนิพจน์อื่นโดยใช้$0บรรทัดปัจจุบัน:

tolower($0) ~ /&&&key word&&&/

หรือ

toupper($0) ~ /&&&KEY WORD&&&/

ดังนั้นคุณมี

awk 'tolower($0) ~ /&&&key word&&&/ { p = ! p ; next }; p' text.txt

คุณต้องใช้เครื่องหมายอัญประกาศเดี่ยวเนื่องจาก$0บล็อก BEGIN สามารถลบออกได้เนื่องจากตัวแปรถูกกำหนดค่าเริ่มต้นเป็นค่าเริ่มต้น""หรือ0เมื่อใช้ครั้งแรกและ{print}เป็นการกระทำเริ่มต้นตามที่ระบุไว้ในความคิดเห็นด้านล่าง


4
awk 'toupper($0)~/&&&KEY WORD&&&/ { p = ! p ; next } ; p;' text.txtโปรดทราบว่าคุณสามารถลดความซับซ้อนที่ ไม่จำเป็นต้องใช้BEGINบล็อกและเนื่องจากการดำเนินการเริ่มต้นคือการพิมพ์p;ก็เพียงพอแล้ว
terdon

1
"ไม่จำเป็นต้องมีการBEGINบล็อก" เนื่องจากตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้นจะประเมินว่าเป็นเท็จ
เกล็นแจ็คแมน

ขอบคุณสำหรับการเพิ่มประสิทธิภาพ ฉันมักจะพยายาม จำกัด การตอบกลับไปที่การเปลี่ยนแปลงเล็กน้อยกับต้นฉบับ แต่มันเป็นความจริงผลลัพธ์ใหม่นั้นแน่นกว่าและอ่านได้ค่อนข้างมาก
meuh

2
ข้อควรทราบ: tolowerมีอยู่ในระบบ awk รุ่นเก่า (หรือไม่โบราณ) (เช่น: AIX) แต่toupperไม่สามารถใช้งานได้เสมอ ^^
Olivier Dulac

16

gawk มีIGNORECASEตัวแปรบิวด์อินซึ่งหากตั้งค่าเป็นไม่ใช่ศูนย์จะทำให้การเปรียบเทียบสตริงและนิพจน์ทั่วไปทั้งหมดเป็นแบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ คุณสามารถใช้สิ่งนั้น:

BEGIN{IGNORECASE=1}
/&&&key word&&&/ { foo bar baz }

แต่นี่เป็นเฉพาะถึงgawkแม้ว่า แต่ฉันคิดว่ามันจะสามารถอ่านได้มากกว่าทางเลือก (พกพา) โดย meuh แน่นอนว่าปัญหานั้นขึ้นอยู่กับคุณอย่างเต็มที่


1
ฉันต้องการสนับสนุน awk เป็นเวลาหลายปีในหนึ่งในโครงการ gawk ที่ยิ่งใหญ่ที่สุดของฉัน แต่การขาดการค้นหาที่ไม่ตอบสนองต่อสิ่งที่เรียกว่า gawk ทำให้มันไม่ใช่การเริ่มต้นเนื่องจากจำนวนการค้นหาที่ไม่ตอบสนองต่อสิ่งต่างๆ gensub เป็นเพ่งพิศอื่น ๆ เท่านั้นที่ยากเกินไปที่จะแทนที่ใน awk แต่ค่าเริ่มต้นของ gawk นั้นไม่ได้ติดตั้งไว้ในเครื่องและดิสทริบิวชั่นบางตัวแม้ว่าจะมีให้ใช้งานเกือบทุกครั้ง แต่ก็โชคร้ายที่ในปี 2559 พวกเขาไม่สามารถเปลี่ยน awk และ posix เพื่อขยายการทำงานของเครื่องมือมาตรฐานดังกล่าวได้
Lizardx

3
@ Lizardx: นั่นคือจุดรวมของการไม่ขยาย: รักษามาตรฐาน ไม่เช่นนั้นคุณจะสร้างมาตรฐานอื่นขึ้นมาจากนั้นคุณก็จะมีความไม่ลงรอยกันระหว่างกัน (พวกเขาทำเช่นนั้น แต่พยายามทำให้การเปลี่ยนแปลงมาตรฐานมีค่าน้อยที่สุด ... ถึงกระนั้นมาตรฐานหลายมาตรฐานก็เป็นหนึ่งในภัยพิบัติหลักของการคำนวณ)
Olivier Dulac

2
ฉันไม่เห็นด้วย ด้วยการดำเนินการอย่างระมัดระวังคุณสามารถแนะนำการขยายตัวในขณะที่สนับสนุนวิธีการดั้งเดิมทั้งหมดจะเกิดอะไรขึ้นถ้าคุณไม่ทำเช่นนั้นสิ่งที่เพิ่งเริ่มจางหายไปเมื่อไม่เกี่ยวข้องกับช่วงเวลา ทุกอย่างในการคำนวณวิวัฒนาการคือเคล็ดลับคือการรักษาวิวัฒนาการที่ไว้วางใจได้อย่างเสถียร Bash เป็นตัวอย่างที่ดีในการทำเช่นนั้นน่าเชื่อถือสุด ๆ และเพียงเพิ่มคุณสมบัติใหม่มันไม่ใช่ 'สองมาตรฐาน' มากนักใช้สิ่งที่ได้รับการสนับสนุนและเมื่อการเปลี่ยนแปลงได้แผ่ขยายไปทั่วโลกคุณสามารถเริ่มใช้คุณสมบัติใหม่ได้เพราะ ระบบเก่าที่เก่าแก่ที่สุดจะไม่ได้รับการสนับสนุน
Lizardx
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.