Задержка после печати строк с помощью sed или awk в большом файле

У меня есть большой файл (1 ГБ), и мне нужно извлечь несколько строк, используя номер записи. Я написал свой сценарий с помощью sed и, так как это заняло слишком много времени, я решил исследовать его. Оказывается, когда я запускаю что-то вроде имени файла sed -n '15689,15696p', печать выполняется быстро, но у меня задержка по времени, и это делает мой сценарий очень медленным. При выполнении той же задачи с помощью awk задержка меньше, но она все еще здесь! Командная строка, которую я использовал для awk, была: awk 'NR>=15689 && NR<=15696' filename

Я попытался напечатать только одну строку (имя файла sed -n '15689p'), и появилась та же проблема!

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

2 ответа

Решение

Избегать использования sed -n '15689,15696p', как sed будет проходить через весь файл. Самый быстрый способ, который я знаю, это:

head -15696 filename | tail -10

Я тестировал его, и он работает намного быстрее:

$ seq 1 100000000 > file

$ time (head -50000000 file | tail -10) > /dev/null
real    0m0.694s
user    0m0.830s
sys     0m0.333s

$ time (sed -n '49999991,50000000p' file) > /dev/null
real    0m6.018s
user    0m5.863s
sys     0m0.160s

$ time (sed -n '50000000q;49999991,50000000p' file) > /dev/null
real    0m3.197s
user    0m3.153s
sys     0m0.043s

$ time (awk 'NR>=49999991 && NR<=50000000' file) > /dev/null
real    0m12.665s
user    0m12.543s
sys     0m0.123s

$ time (awk 'NR>=49999991 && NR<=50000000{print} NR==50000001{exit}' file)
real    0m9.104s
user    0m9.010s
sys     0m0.100s

Это потому, что он сканирует прямо в конец файла. Попробуйте это выйти после печати:

sed -ne '15690q;15689p' file

Или с помощью awk:

awk 'NR>=15689 && NR<=15696{print} NR==15697{exit}' filename

Просто для удовольствия я запустил тайминги @RichardHum, и у меня полностью противоположность на OSX Mavericks с SSD-диском:

#!/bin/bash -xv
seq 1 100000000 > file
time (head -50000000 file | tail -10) > /dev/null
time (sed -n '50000000q;49999991,50000000p' file) > /dev/null
time (awk 'NR>=49999991 && NR<=50000000{print} NR==50000001{exit}' file)
time (head -50000000 file | tail -10) > /dev/null

и я получил:

time (head -50000000 file | tail -10) > /dev/null
real    0m29.565s
user    0m35.711s
sys 0m0.733s

time (sed -n '50000000q;49999991,50000000p' file) > /dev/null
real    0m13.313s
user    0m13.162s
sys 0m0.150s

time (awk 'NR>=49999991 && NR<=50000000{print} NR==50000001{exit}' file)
real    0m7.433s
user    0m7.293s
sys 0m0.139s

time (head -50000000 file | tail -10) > /dev/null
real    0m29.560s
user    0m35.697s
sys 0m0.742s

Я даже запустил решение "голова + хвост" в конце, если оно не принесло пользы от кэширования в первый раз, но оно определенно медленнее!

Другие вопросы по тегам