2016-09-03 2 views
0

я в настоящее время использую длинный конвейер bash команды для извлечения данных из текстовых файлов, как это, где $ е моего файл:Быстрая альтернатива grep-файлу несколько раз?

result=$(grep "entry t $t " $f | cut -d ' ' -f 5,19 | \ 
     sort -nk2 | tail -n 1 | cut -d ' ' -f 1) 

Я использую скрипт, который мог бы сделать сотни подобных поисков $ е , сортировка выбранных строк различными способами в зависимости от того, что я вытаскиваю. Мне нравятся однострочные строки bash с букетом труб, потому что он компактен и прост, но может потребоваться навсегда. Может ли кто-нибудь предложить более быструю альтернативу? Может быть, что-то, что сначала загружает весь файл в память?

Благодаря

+2

Вы правы: он медленный и будет продолжаться, потому что grep читает с диска, а также ищет строки линейно. Похоже, вы готовы к использованию python и его словарей ... Если вы разместили [mcve] с вашим кодом, образец ввода и ожидаемый результат, я могу что-то придумать. –

+0

, до этого вы могли бы подготовить суб-списки с заранее подготовленными шаблонами, поэтому поиск в этих подписях будет быстрее. –

+3

Трудно сказать, пока вы не представите конкретные примеры того, как выглядят ваши файлы, и чего вы пытаетесь достичь, и какова ваша машина. Возможно, параллельный поиск с помощью GNU Parallel, возможно, 'awk', может быть, Perl. Ваш вопрос очень широк. –

ответ

0

Вы можете получить импульс с делать всю трубу с gawk или другой awk, который имеет asorti, выполнив:

contents="$(cat "$f")" 
result="$(awk -vpattern="entry t $t" '$0 ~ pattern {matches[$5]=$19} END {asorti(matches,inds); print inds[1]}' <<<"$contents")" 

Это будет читать «$ F» в переменную, то мы» Используйте одну команду awk (ну, gawk в любом случае), чтобы выполнить всю оставшуюся работу. Вот как это работает:

  • -vpattern = «вход т $ т»: определяет awk переменную с именем pattern, который содержит переменной оболочки t
  • $ 0 ~ шаблон матчи текущую строку с шаблоном , если оно соответствует мы сделаем часть в фигурных скобках, в противном случае мы пропускаем его
    • матчи [$ 5] = $ 19 добавляет запись в массив (и создает массив, если урожденная DED), где ключевым является пятым поле, а значение 19
  • END сделать следующую функцию после того, как все входные были обработаны
    • Asorti (спичек, аким) Сортировка записи о matches таким образом, что inds является массив, содержащий порядок ключей в matches, чтобы получить значение в отсортированном порядке
    • печать аким [1] печатает индекс в матчах (т.е. $ 5 от Befor е) связан с наименьшим 19 поля
  • < < < «$ содержание» имеют awk работу по значению переменной оболочки contents, как если бы это был файл он читал

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

Вам нужно будет проверить, действительно ли это происходит быстрее или нет, и если производительность важна, вам действительно нужно подумать о переходе на «правильный» язык вместо сценариев оболочки.

0

Поскольку вы не предоставили образец ввода/вывода, это всего лишь предположение, и я публикую его только потому, что уже есть другие ответы, которые вы не должны делать, так что это может быть то, что вы хотите, а не одну строку:

result=$(awk -v t="$t" ' 
    BEGIN { regexp = "entry t " t " " } 
    $0 ~ regexp { 
     if (($6 > maxKey) || (maxKey == "")) { 
      maxKey = $6 
      maxVal = $5 
     } 
    } 
    END { print maxVal } 
' "$f") 

Я подозреваю, ваш вопрос реальной производительности, однако, не то, что сценарий, но что вы работаете его и, возможно, другие внутри цикла, что вы не показали нам. Если да, см. why-is-using-a-shell-loop-to-process-text-considered-bad-practice и отправьте лучший пример, чтобы мы могли вам помочь.

Смежные вопросы