ฉันพยายามหาวิธีกรองบรรทัดที่มีคำว่า "มะนาว" และ "ข้าว" อยู่ในนั้น ฉันรู้วิธีหา "มะนาว" หรือ "ข้าว" แต่ไม่ใช่ทั้งสองอย่าง พวกเขาไม่จำเป็นต้องอยู่ถัดจากข้อความอื่นเพียงแค่บรรทัดเดียว
ฉันพยายามหาวิธีกรองบรรทัดที่มีคำว่า "มะนาว" และ "ข้าว" อยู่ในนั้น ฉันรู้วิธีหา "มะนาว" หรือ "ข้าว" แต่ไม่ใช่ทั้งสองอย่าง พวกเขาไม่จำเป็นต้องอยู่ถัดจากข้อความอื่นเพียงแค่บรรทัดเดียว
คำตอบ:
"ทั้งคู่ในบรรทัดเดียวกัน" หมายถึง "'ข้าว' ตามด้วยตัวอักษรสุ่มตามด้วย 'มะนาว' หรือวิธีอื่น ๆ '
ใน regex ที่เป็นหรือrice.*lemon
lemon.*rice
คุณสามารถรวมที่ใช้|
:
grep -E 'rice.*lemon|lemon.*rice' some_file
หากคุณต้องการใช้ regex ปกติแทนที่จะเป็นส่วนขยาย ( -E
) คุณต้องมีแบ็กสแลชก่อน|
:
grep 'rice.*lemon\|lemon.*rice' some_file
สำหรับคำที่ยาวขึ้นอย่างรวดเร็วและมักจะใช้งานได้ง่ายขึ้นหลายสายgrep
เช่น:
grep rice some_file | grep lemon | grep chicken
grep rice
rice
มันถูกป้อนเข้าgrep lemon
ซึ่งจะพบเพียงบรรทัดที่มีมะนาว .. และอื่น ๆ ในขณะที่ OP - เช่นเดียวกับคำตอบของคุณก่อน - จะช่วยให้การใด ๆของ [ข้าว | มะนาว | ไก่]
|
จะต้องหนีgrep
? ขอบคุณ!
egrep
ใช้ Extended regex ที่|
เข้าใจว่าเป็นตรรกะหรือ grep
เริ่มต้นที่ regex ขั้นพื้นฐานซึ่ง\|
เป็น OR
grep
manpage 's, เลิกและควรถูกแทนที่ด้วยegrep
grep -E
ฉันใช้เสรีภาพในการแก้ไขคำตอบตามนั้น
คุณสามารถไพพ์เอาต์พุตของคำสั่ง grep แรกไปยังคำสั่ง grep อื่นและจะจับคู่ทั้งสองรูปแบบ ดังนั้นคุณสามารถทำสิ่งที่ชอบ:
grep <first_pattern> <file_name> | grep <second_pattern>
หรือ,
cat <file_name> | grep <first_pattern> | grep <second_pattern>
เพิ่มเนื้อหาลงในไฟล์ของเรา:
$ echo "This line contains lemon." > test_grep.txt
$ echo "This line contains rice." >> test_grep.txt
$ echo "This line contains both lemon and rice." >> test_grep.txt
$ echo "This line doesn't contain any of them." >> test_grep.txt
$ echo "This line also contains both rice and lemon." >> test_grep.txt
ไฟล์ประกอบด้วยอะไรบ้าง:
$ cat test_grep.txt
This line contains lemon.
This line contains rice.
This line contains both lemon and rice.
This line doesn't contain any of them.
This line also contains both rice and lemon.
ตอนนี้ลอง grep สิ่งที่เราต้องการ:
$ grep rice test_grep.txt | grep lemon
This line contains both lemon and rice.
This line also contains both rice and lemon.
เรารับเฉพาะเส้นที่ทั้งสองรูปแบบตรงกันเท่านั้น คุณสามารถขยายสิ่งนี้และไพพ์เอาต์พุตไปยังคำสั่ง grep อื่นสำหรับการจับคู่ "AND" เพิ่มเติม
แม้ว่าคำถามจะถามถึง 'grep' แต่ฉันคิดว่าอาจเป็นประโยชน์ในการโพสต์วิธีแก้ปัญหา 'awk' ที่เรียบง่าย:
awk '/lemon/ && /rice/'
สิ่งนี้สามารถขยายได้อย่างง่ายดายด้วยคำที่มากขึ้นหรือการแสดงออกแบบบูลอื่น ๆ นอกเหนือจาก 'และ'
grep พร้อมตัวเลือก-P
(Perl-Compatibility)และregex lookahead เชิงบวก(?=(regex))
:
grep -P '(?=.*?lemon)(?=.*?rice)' infile
หรือคุณสามารถใช้ด้านล่างแทน:
grep -P '(?=.*?rice)(?=.*?lemon)' infile
.*?
วิธีการที่ตรงกับตัวอักษรใด ๆ.
ที่เกิดขึ้นเป็นศูนย์ครั้งหรือมากกว่า*
ในขณะที่พวกเขาเป็นตัวเลือกตามรูปแบบ ( rice
หรือlemon
) ?
ทำให้ไม่จำเป็นทุกอย่างก่อนที่มัน (หมายถึงการเป็นศูนย์หรือเวลาหนึ่งทุกอย่างจับคู่.*
)(?=pattern)
: Positive Lookahead: โครงสร้าง Lookahead เชิงบวกคือวงเล็บหนึ่งคู่โดยมีวงเล็บเปิดตามด้วยเครื่องหมายคำถามและเครื่องหมายเท่ากับ
ดังนั้นสิ่งนี้จะส่งคืนบรรทัดทั้งหมดที่มีทั้งแบบสุ่มlemon
และrice
แบบสุ่ม นอกจากนี้จะหลีกเลี่ยงการใช้|
และสองเท่าgrep
s
ลิงก์ภายนอก:
หัวข้อ Grep ขั้นสูงLookahead เชิงบวก - GREP สำหรับนักออกแบบ
grep -e foo -e goo
จะส่งคืนการจับคู่สำหรับ foo หรือ goo
หากเรายอมรับว่าการให้คำตอบที่ไม่ได้grep
ใช้นั้นเป็นที่ยอมรับเช่นเดียวกับคำตอบข้างต้นawk
ฉันก็ขอเสนอperl
บรรทัดง่ายๆเช่น:
$ perl -ne 'print if /lemon/ and /rice/' my_text_file
การค้นหาสามารถละเว้นตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ / บางคำ/lemon/i and /rice/i
ทั้งหมด ในเครื่องส่วนใหญ่ของ Unix / Linux นั้นมีการติดตั้งรวมทั้ง awk อยู่ดี
ต่อไปนี้เป็นสคริปต์เพื่อทำให้โซลูชันการวางท่อ grep เป็นอัตโนมัติ:
#!/bin/bash
# Use filename if provided as environment variable, or "foo" as default
filename=${filename-foo}
grepand () {
# disable word splitting and globbing
IFS=
set -f
if [[ -n $1 ]]
then
grep -i "$1" ${filename} | filename="" grepand "${@:2}"
else
# If there are no arguments, assume last command in pipe and print everything
cat
fi
}
grepand "$@"
eval
แล้วนำไปแบ่งซึ่งจะแตกง่าย