Я ищу самый простой способ напечатать самую длинную строку в файле. Я немного погуглил и неожиданно не смог найти ответ. Я часто печатаю длину самой длинной строки в файле, но я не знаю, как на самом деле напечатать самую длинную строку. Кто-нибудь может предложить решение для печати самой длинной строки в файле? Заранее спасибо.
35
Ответы:
UPD : обобщение всех советов в комментариях
источник
cat
), и использование канала являются дорогостоящими операциями, не говоря уже о том, что для awk более эффективно просто читать файл. Влияние на производительность определенно заметно, если это делается часто, и даже в этом случае вы полностью злоупотребляетеcat
.cat
здесь не бесполезно. Это может быть бесполезно для компьютера, но для человека-читателя это может обеспечить ценность. Первый вариант четко показывает входные данные. Поток более естественный (слева направо). Во втором случае вы не знаете, что это за ввод, если не прокрутите окно.cat
.< file command
работает просто отлично.< filename command
эквивалентноfilename < command
в каждой оболочке, которую я пробовал. Но как только вы узнаете об этом, вы сможете воспользоваться этим при написании длинных каналов, которые четко показывают направление потока данных (без вызова дополнительной команды):< input-file command1 | command2 | command3 > output-file
источник
Сначала он читает файл внутри подстановки команд и выводит длину самой длинной строки (ранее
expand
конвертирует табуляцию в пробелы, чтобы преодолеть семантикуwc -L
- каждая вкладка в строке будет добавлять 8 вместо 1 к длине строки). Затем эта длина используется вsed
выражении, означающем «найти строку с таким количеством символов, напечатать ее и выйти». Так что это на самом деле может быть настолько оптимальным, так как самая длинная строка находится рядом с верхом файла, хе-хе (спасибо большое за потрясающие и конструктивные комментарии).Другой, я думал раньше, чем sed (в bash):
источник
-L, --max-line-length
печатает длину самой длинной строки, в соответствии с man-страницей, но если вы копаете глубже (например, когда вы получаете неправильные / неожиданные результаты), вы обнаружите, что эта опция увеличивает длину на 8 для каждого 1 символа табуляции\x09
посмотреть этот Unix & Linux Q / Ased -rn "/.{$(<file expand -t1 |wc -L)}/p" file
read line
будет интерпретировать обратные косую черту символов как буквальный полукокс, например\A
resloves кA
, которые, конечно , эффективны отчеты короче , чем фактические байтовое использование ... Для того, чтобы предотвратить эту сбежавшую интерпретацию, использование:read -r line
. , , , Кроме того, чтобы заставить версию sed + wc выйти после первой «самой длинной строки», изменитеp
на{p;q}
..sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file
Вот решение Perl:
Или, если вы хотите напечатать все самые длинные строки
Поскольку у меня не было ничего лучше, я запустил несколько тестов для текстового файла 625M. Удивительно, но мое решение на Perl было последовательно быстрее, чем другие. Конечно, разница с принятым
awk
решением крошечная, но она есть. Очевидно, что решения, которые печатают несколько строк, работают медленнее, поэтому я отсортировал их по типу, быстрее и медленнее.Выведите только одну из самых длинных строк:
Вывести все самые длинные строки:
источник
Grep первая самая длинная линия
Команда необычно трудна для чтения без практики, потому что она смешивает синтаксис оболочки и регулярных выражений.
Для объяснения я сначала буду использовать упрощенный псевдокод. Строки, начинающиеся с
##
, не запускаются в оболочке.Этот упрощенный код использует имя файла F и оставляет для удобства чтения кавычки и части регулярных выражений.
Как это работает
Команда состоит из двух частей:
grep
- иwc
вызова:## grep "^.{$( wc -L F )}$" F
wc
Используется в расширении процесса,$( ... )
так оно выполняется доgrep
. Он рассчитывает длину самой длинной строки. Синтаксис расширения оболочки смешивается с синтаксисом шаблона регулярного выражения в некоторой путанице, поэтому я разложу расширение процесса:## wc -L F
42
## grep "^.{42}$" F
Здесь расширение процесса было заменено на возвращаемое значение, создавая используемую
grep
командную строку. Теперь мы можем более легко прочитать регулярное выражение: оно точно соответствует от начала (^
) до конца ($
) строки. Выражение между ними соответствует любому символу, кроме новой строки, повторяется 42 раза. В совокупности это строки, состоящие ровно из 42 символов.Теперь вернемся к реальным командам оболочки:
grep
опция-E
(--extended-regexp
) позволяет избежать экранирования{}
. Option-m 1
(--max-count=1
) останавливает ее после того, как найдена первая строка. Команда<
inwc
записывает файл в его стандартный ввод, чтобы предотвратитьwc
печать имени файла вместе с длиной.Какие самые длинные строки?
Чтобы сделать примеры более удобочитаемыми, когда имя файла встречается дважды, я буду использовать переменную
f
для имени файла; Каждый$f
в примере может быть заменен именем файла.Показать первую самую длинную строку - первую строку длиной до самой длинной строки:
Показать все самые длинные строки - все строки длиной до самой длинной строки:
Показать последнюю самую длинную строку - последнюю строку длиной до самой длинной строки:
Показать одну самую длинную строку - самая длинная строка длиннее всех других строк или ошибка:
(Последняя команда даже более неэффективна, чем другие, поскольку она повторяет полную команду grep. Очевидно, что она должна быть разложена таким образом, чтобы выходные данные
wc
и строки, записанные с помощьюgrep
, сохранялись в переменные.Обратите внимание, что все самые длинные строки могут фактически быть всеми строками Для сохранения в переменной необходимо сохранить только первые две строки.)
источник
Следующий пример должен был быть и должен был быть комментарием к ответу dmitry.malikov , но из-за бесполезного использования видимого пространства комментариев там я решил представить его здесь, где он, по крайней мере, будет виден. ..
Это простое изменение в ДМИТРИЙ по методу AWK однопроходной.
Он печатает все «равные самые длинные» строки. (Примечание.
delete array
Является расширением Gawk).источник
В чистом виде:
источник
_max_line[0]=${_line}
не удалит оставшуюся часть ранее накопленных более коротких «длинных линий» ...unset _max_line
очистит весь массив ...Я разработал небольшой скрипт для этого. Он отображает длину, номер строки и саму строку по длине, которая превышает определенный размер, например, 80 символов:
https://github.com/lordofrain/tools/blob/master/longest-line/longest-line.sh
источник
$*
редко хорошая идея, вы хотите"$@"
. The/.*/
in yourawk
ничего не делает, так как это также соответствует пустым строкам. Вы могли бы избежать экранирования,\$0
если бы вы указали одинарную кавычку'EOF'
. Зачем использовать пустойBEGIN{}
блок? Наконец, вам не нужноcat
, простоawk . . . "$file" | . . .
awk -vmax=15 '{len=length($0); if(len>=max){printf("%s, %d at line # %d %s\n", FILENAME, len, NR, $0);}}' file*
Вы можете использовать
wc
:источник
wc -L
недостатка.