У меня есть образ диска 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К символов.