Який хороший спосіб вилучити скажімо, рядки 20 -45 з величезного текстового файлу. Безумовно інтерактивно!
Який хороший спосіб вилучити скажімо, рядки 20 -45 з величезного текстового файлу. Безумовно інтерактивно!
Відповіді:
ви можете спробувати:
cat textfile | head -n 45 | tail -n 26
або
cat textfile | awk "20 <= NR && NR <= 45"
оновлення:
Як вказував Махомедалід, catце не потрібно і трохи зайве, але це робить для чистої, читабельної команди.
Якщо catвас турбує, кращим заспокоєнням буде:
<textfile awk "20 <= NR && NR <= 45"
,оператор дальності діапазону awk .
Ще простіше:
sed -n '20,45p;45q' < textfile
Прапор -n відключає вихід за замовчуванням. "20,45" адресує рядки 20 - 45 включно. Команда "p" друкує поточний рядок. І q припиняється після друку рядка.
qкоманди (все, починаючи з ;) покращило продуктивність для мене при витягуванні одного рядка 26995107 з файлу рядків 27169334.
Це не відповідь, але не можна розмістити її як коментар.
Ще один (дуже швидкий) спосіб зробити це запропоновано mikeserv тут :
{ head -n 19 >/dev/null; head -n 26; } <infile
Використовуючи той самий тестовий файл, що і тут, та ж процедура, ось деякі орієнтири (вилучення рядків 1000020-1000045):
mikeserv :
{ head -n 1000019 >/dev/null; head -n 26; } <iplist
real 0m0.059s
Стефан :
head iplist -n 1000045 | tail -n 26
real 0m0.054s
Це, безумовно, найшвидші рішення, і відмінності незначні (для одного проходу) (я намагався з різними діапазонами: пара рядків, мільйони рядків тощо).
Виконання цього без труби може принести значну перевагу додатку, який потребує пошуку декількох діапазонів ліній подібним чином:
for pass in 0 1 2 3 4 5 6 7 8 9
do printf "pass#$pass:\t"
head -n99 >&3; head -n1
done <<1000LINES 3>/dev/null
$(seq 1000)
1000LINES
... які друкує ...
pass#0: 100
pass#1: 200
pass#2: 300
pass#3: 400
pass#4: 500
pass#5: 600
pass#6: 700
pass#7: 800
pass#8: 900
pass#9: 1000
... і читає файл лише один раз.
Інші sed/ awk/ perlрішення читають весь файл, і оскільки мова йде про величезні файли, вони не дуже ефективні. Я підкинув кілька альтернатив, що exitабо quit після останнього рядка у вказаному діапазоні:
Стефан :
awk "1000020 <= NR && NR <= 1000045" iplist
real 0m2.448s
vs.
awk "NR >= 1000020;NR==1000045{exit}" iplist
real 0m0.243s
dkagedal ( sed):
sed -n 1000020,1000045p iplist
real 0m0.947s
vs.
sed '1,1000019d;1000045q' iplist
real 0m0.143s
Стівен D :
perl -ne 'print if 1000020..1000045' iplist
real 0m2.041s
vs.
perl -ne 'print if $. >= 1000020; exit if $. >= 1000045;' iplist
real 0m0.369s
awk NR==1000020,NR==1000045 textfileу вашій системі.
ruby -ne 'print if 20 .. 45' file
python -c 'import fileinput, sys; [sys.stdout.write(line) for nr, line in enumerate(fileinput.input()) if 19 <= nr <= 44]'? :-P Це те, що Рубі, за взірцем Perl, натхненним awk / sed, може легко зробити.
Оскільки sed і awk вже були прийняті, ось рішення Perl:
perl -nle "print if ($. > 19 && $. < 46)" < textfile
Або, як зазначено в коментарях:
perl -ne 'print if 20..45' textfile
perl -ne'print if 20..45' textfile
awk NR==20,NR==45 textfileтакож працює і легко читається.