Назад | Перейти на главную страницу

Команда оболочки Linux для фильтрации текстового файла по длине строки

У меня есть образ диска 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), который будет фильтровать файл по длине строки?

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

напечатает строки короче 16 килобайт, как в вашем собственном примере.

Или, если вам нравится Perl:

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

Это похоже на ответ Ансгара, но немного быстрее в моих тестах:

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

Не очень отличается от уже приведенных ответов, но все же короче:

awk -F '' 'NF < 16384' infile >outfile

Ты можешь awk Такие как:

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

Это напечатает строки короче 16К символов (16 * 1024).

Ты можешь использовать grep также:

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

Это напечатает строки не более 16К символов.