Який найкращий спосіб витягнути сегмент із текстового файлу?


Відповіді:


12

ви можете спробувати:

cat textfile | head -n 45 | tail -n 26

або

cat textfile | awk "20 <= NR && NR <= 45" 

оновлення:

Як вказував Махомедалід, catце не потрібно і трохи зайве, але це робить для чистої, читабельної команди.

Якщо catвас турбує, кращим заспокоєнням буде:

<textfile awk "20 <= NR && NR <= 45"

2
awk NR==20,NR==45 textfileтакож працює і легко читається.
ефеміент

Мені більше подобається використання stdin, воно має деяку глобальну узгодженість з рештою nix
Стефан

1
Читання аргументів командного рядка також відповідає іншим утилітам UNIX, і моя головна суть полягала в тому, щоб продемонструвати ,оператор дальності діапазону awk .
ефеміент

хаха, я мав на увазі @adam. але так, мені подобається ваша пропозиція
Стефан

Я думаю, що відповідь @ ephemient найкраща тут. В іншому випадку команди є досить виразними.
Лео Леопольд Герц 준영

13

Ще простіше:

sed -n '20,45p;45q' < textfile

Прапор -n відключає вихід за замовчуванням. "20,45" адресує рядки 20 - 45 включно. Команда "p" друкує поточний рядок. І q припиняється після друку рядка.


1
+1 приємно, мені подобається, але його лінія 20 на 45 :)
Стефан

1
гаразд добре, я відредагував це так, щоб сказати 20,45 :-)
dkagedal

Видалення qкоманди (все, починаючи з ;) покращило продуктивність для мене при витягуванні одного рядка 26995107 з файлу рядків 27169334.
Руслан

6

Це не відповідь, але не можна розмістити її як коментар.

Ще один (дуже швидкий) спосіб зробити це запропоновано 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

+1 Я думаю, що це найкраща відповідь тут! Було б непогано отримати скільки часу потрібно для цього awk NR==1000020,NR==1000045 textfileу вашій системі.
Лео Леопольд Герц 준영

3
ruby -ne 'print if 20 .. 45' file

1
товариш рубіст, ви отримуєте мій голос, сер
Стефан

1
Поки ми на цьому, чому б і не python -c 'import fileinput, sys; [sys.stdout.write(line) for nr, line in enumerate(fileinput.input()) if 19 <= nr <= 44]'? :-P Це те, що Рубі, за взірцем Perl, натхненним awk / sed, може легко зробити.
ефеміент

2

Оскільки sed і awk вже були прийняті, ось рішення Perl:

perl -nle "print if ($. > 19 && $. < 46)" < textfile

Або, як зазначено в коментарях:

perl -ne 'print if 20..45' textfile

2
Що з усіма цими зайвими символами? Немає необхідності знімати та повторно додавати нові рядки, flip-flop передбачає порівняння з номером рядка, а оператор алмазу виконує аргументи, якщо вони надані. perl -ne'print if 20..45' textfile
ефемія

1
Приємно. -nle - це трохи рефлекс, я думаю, що стосується решти, у мене немає виправдань, крім збереження незнання.
Стівен Д
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.