Задержка после печати строк с помощью 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
Я даже запустил решение "голова + хвост" в конце, если оно не принесло пользы от кэширования в первый раз, но оно определенно медленнее!