Команда оболонки Linux для фільтрації текстового файлу за довжиною рядка


19

У мене є 30-футовий диск із зображенням захищеного розділу (думаю dd if=/dev/sda1 of=diskimage), з якого мені потрібно відновити деякі текстові файли. Інструменти для різьблення даних, як-от, foremostпрацюють лише у файлах із чітко визначеними заголовками, тобто не просто текстовими файлами, тому я повернувся до свого доброго друга strings.

strings diskimage > diskstrings.txt створив текстовий файл 3 Гб, що містить купу рядків, здебільшого марних речей, змішаних із текстом, який я насправді хочу.

Більшість суглобів мають тенденцію бути справді довгими, нерозривними струнами гнучкості. Мене, що мене цікавить, гарантовано менше 16 Кбіт, тому я збираюсь фільтрувати файл за довжиною рядка. Ось сценарій Python, який я використовую для цього:

infile  = open ("infile.txt" ,"r");
outfile = open ("outfile.txt","w");
for line in infile:
    if len(line) < 16384:
        outfile.write(line)
infile.close()
outfile.close()

Це працює, але для довідки в майбутньому: Чи є магічна однолінійних змови (думає awk, sed) , який буде фільтрувати файл по довжині лінії?

Відповіді:


28
awk '{ if (length($0) < 16384) print }' yourfile >your_output_file.txt

буде надруковано рядки коротшими за 16 кілобайт, як у вашому власному прикладі.

Або якщо ви любите Perl:

perl -nle 'if (length($_) < 16384) { print }' yourfile >your_output_file.txt

Ну, це було бентежно просто. Дякую. :)
Li-aung Yip

Додана також версія Perl :-)
Janne Pikkarainen

А сценарій awk може бути записаний як awk 'length($0) < 16384' file > output, оскільки дією за замовчуванням є друк рядка.
glenn jackman

8

Це схоже на відповідь Ансгара, але трохи швидше в моїх тестах:

awk 'length($0) < 16384' infile >outfile

Це така ж швидкість, як і інші відповіді awk. Він покладається на неявний printістинний вираз, але не потрібно витрачати час, щоб розділити лінію, як це робить Ансгар.

Зауважте, що AWK дає вам ifбезкоштовно. Наведена вище команда еквівалентна:

awk 'length($0) < 16384 {print}' infile >outfile

Немає явного if(або його оточуючого набору фігурних дужок), як в деяких інших відповідях.

Ось як це зробити sed:

sed '/.\{16384\}/d' infile >outfile

або:

sed -r '/.{16384}/d' infile >outfile

які видаляють будь-який рядок, що містить 16384 (або більше) символів.

Для повноти ознайомтеся з описаними нижче способами sedзбереження рядків, що перевищують поріг:

sed '/^.\{0,16383\}$/d' infile >outfile

2

Ви можете awk:

$ awk '{ if (length($0) < 16384) { print } }' /path/to/text/file

Це надрукує рядки довше 16 К символів (16 * 1024).

Ви також можете використовувати grep:

$ grep ".\{,16384\}" /path/to/text/file

Це надрукує рядки максимум 16 К символів.


Не впевнений, grepчи така гарна ідея - це, звичайно, простий регепс, але обчислювально дорожчий ніж awk. "Людина з проблемою каже:" Я буду використовувати регулярні вирази! Зараз у нього дві проблеми ". ;)
Лі-аун Іп

Це просто інший спосіб зробити це. Перший варіант, який я розмістив, - це використання awk.
Халед

1
+1 для regexp, тому що це гольфи краще, і це не змушує мене читати awk manpages =)
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

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