соответствие нескольких шаблонов несколько раз с помощью awk - PullRequest
1 голос
/ 28 февраля 2012

Я пытаюсь эффективно сопоставлять несколько шаблонов одновременно, что в принципе работает очень хорошо:

echo abcdef | awk \
'/abc/ {print "match abc"}
 /def/ {print "match def"}'

Дополнительно я хочу сопоставить все вхождения в записи:

echo abcabc | awk \
'function findall(str, re) {
    while(match(str, re)) {
        print "match", re;
        str = substr(str, RSTART+RLENGTH)
    }
}
{
    findall($0, "abc");
}'

Теперь, чтобы расширить приведенный выше пример для соответствия нескольким шаблонам, я бы закончил серией вызовов findall:

findall($0, "abc");
...
findall($0, "def");

Проблема в том, что при много разных шаблонов (> 100) этот подход работает не так хорошо, как первый пример.В этом есть смысл, так как паттерн не заканчивается в том же автомате, я думаю.

Есть ли способ немного ускорить процесс?например, обеспечение «совпадения» с несколькими шаблонами.Я думаю, что я мог бы объединить шаблоны (abc | def), но тогда я потерял бы информацию, какой шаблон был именно тем, который соответствовал.

Обновление: Каждое вхождение должно совпадать:

abcabc
123
abcxyz

в качестве входных данных приводит к 2 совпадающим записям (с учетом стандартного разделителя), но 4 совпадает во всех данных , если используется с шаблонами "abc" и«хуг».Первый пример в этом посте по крайней мере сообщает о 3 совпадениях , но не обнаруживает множественные вхождения «abc» в первой записи

1 Ответ

2 голосов
/ 28 февраля 2012

как насчет этого:

Вы помещаете свои шаблоны в файл, каждый шаблон в строку, а не в функцию awk.

, например

kent$  cat p.txt
abc
def
foo
xxx

тогда вы можете загрузить файл, и пусть awk сделает соответствующую работу за вас. в конце выведите только те шаблоны, которые соответствуют вашей входной строке:

    echo inputString|awk 'NR==FNR{ps[$0]=0;next;}
{for(p in ps)if(match($0,p))ps[p]++;}
END{for(p in ps) if(ps[p]>0)print p" matched"}' p.txt -

Конечно, вы можете заменить «-» на входной файл, если вам нужно.

небольшой тест:

kent$  echo "abcdefoobarblah"|awk 'NR==FNR{ps[$0]=0;next;}{for(p in ps)if(match($0,p))ps[p]++;}END{for(p in ps) if(ps[p]>0)print p" matched"}' p.txt -
def matched
foo matched
abc matched

Итак, шаблон "ххх" не был найден. были напечатаны только def, foo, abc.

Обратите внимание , что скрипт можно оптимизировать и сделать короче. например, сохранить блок END {}, выполнить печать в первом цикле for. тем не менее, он показывает вам мою идею, как это сделать.

РЕДАКТИРОВАТЬ для комментария ОП

Джо, я не видел требования о времени совпадения в твоем вопросе. однако это не сложно достичь. Смотрите тест ниже с вашим примером текста:

kent$  echo "abcabcabcdefoobarblah"|
awk 'NR==FNR{ps[$0]=0;next;}
{for(p in ps){t=$0;ps[p]=gsub(p,"",t);}}
END{for(p in ps) if(ps[p]>0)print p" matched "ps[p]" time(s)"}' p.txt -

выход:

def matched 1 time(s)
foo matched 1 time(s)
abc matched 3 time(s)
...