Не намагайтеся використовувати grep для цього, використовуйте awk. Для того, щоб відповідати 2 регулярними виразами R1 та R2 в греппі, ви вважаєте, що це буде:
grep 'R1.*R2|R2.*R1'
тоді як у розпаді це було б:
awk '/R1/ && /R2/'
але що робити, якщо R2
перекривається або є підмножиною R1
? Ця команда grep просто не працює, тоді як команда awk буде. Скажімо, ви хочете знайти рядки, які містять the
та heat
:
$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
Для цього вам доведеться використовувати 2 грейпи та трубу:
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
і звичайно, якщо ви насправді вимагали, щоб вони були окремими, ви завжди можете писати у awk той же regexp, який ви використовували в grep, і є альтернативні рішення awk, які не передбачають повторення регулярних виразів у кожній можливій послідовності.
Відклавши це в бік, що робити, якщо ви хочете поширити своє рішення на 3 повторних вираза R1, R2 та R3. В грепі, це був би один із таких поганих варіантів:
grep 'R1.*R2.*R3|R1.*R3.*R2|R2.*R1.*R3|R2.*R3.*R1|R3.*R1.*R2|R3.*R2.*R1' file
grep R1 file | grep R2 | grep R3
хоча в awk це буде стислим, очевидним, простим, ефективним:
awk '/R1/ && /R2/ && /R3/'
Тепер, що робити, якщо ви насправді хотіли відповідати буквальним рядкам S1 і S2 замість регулярних виразів R1 і R2? Ви просто не можете цього зробити за один виклик grep, вам потрібно або написати код, щоб уникнути всіх метахараторів RE, перш ніж викликати grep:
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
або знову використовуйте 2 грейпи та трубу:
grep -F 'S1' file | grep -F 'S2'
що знову поганий вибір, тоді як з awk ви просто використовуєте струнний оператор замість оператора regexp:
awk 'index($0,S1) && index($0.S2)'
Тепер, що робити, якщо ви хотіли відповідати 2 повторними виразами в абзаці, а не рядку? Не можна робити grep, trivial in awk:
awk -v RS='' '/R1/ && /R2/'
Як щодо цілого файлу? Знову не можна робити греп і тривіально в awk (на цей раз я використовую GNU awk для багатоканальної RS для стисності, але це не набагато більше коду в будь-якому awk, або ви можете вибрати контрольну схему, яку ви не знаєте бути у вході для RS, щоб зробити те саме):
awk -v RS='^$' '/R1/ && /R2/'
Отже - якщо ви хочете знайти кілька рядків або рядків у рядку чи абзаці чи файлі, тоді не використовуйте grep, використовуйте awk.