Как распечатать самую длинную строку в файле?

ls -alct /root -> корневой корневой каталог создается во время установки

35
23.04.2012, 08:06
10 ответов
cat ./text | awk ' { if ( length > x ) { x = length; y = $0 } }END{ print y }'

UPD: суммирование всех советов в комментариях

awk 'length > max_length { max_length = length; longest_line = $0 } END { print longest_line }' ./text 
39
27.01.2020, 19:36
  • 1
    Это, оба вызова другой команды (cat), и использование канала является дорогими операциями, не говоря уже о том, что более эффективно для awk просто считать файл. Последствия производительности определенно примечательны, если это часто делается, и несмотря на это, Вы полностью неправильно используете cat. –  Chris Down 13.11.2011, 04:37
  • 2
    @laebshade Там абсолютно является причиной - это так, Вы не должны помнить, какие команды берут имена файлов и которые не делают или заботятся, о котором команда собирается выполниться сначала в конвейере. Если Вы собираетесь быть записью скрипта, который часто запускается, любой ценой волнуйтесь о чем-то вроде этого. Если Вы пишете одноразовую вещь найти самую длинную строку в файле, дополнительный процесс и дробное использованное количество времени абсолютно не важны. Глупо, что люди так одержимы им здесь, это невероятно незначительно –  Michael Mrozek♦ 13.11.2011, 19:41
  • 3
    @Keith Thompson: cat не бесполезно здесь. Это могло бы быть бесполезно к компьютеру, но для читателя это могло обеспечить значение. Первый вариант ясно показывает вход. Поток является более естественным (слева направо). Во втором случае Вы не знаете то, что - вход то, если Вы не прокручиваете окно. –  jfs 14.11.2011, 05:02
  • 4
    @J.F.Sebastian, Даже если Вы хотите это слева, Вам не нужно cat. < file command работает просто великолепно. –  Chris Down 14.11.2011, 05:03
  • 5
    @J.F.Sebastian: то, что перенаправление может быть записано в начале команды, несколько неясно; < filename command эквивалентно filename < command в каждой оболочке я попробовал. Но после того как Вы знаете о нем, можно использовать в своих интересах его, когда запись долго передает по каналу, которые ясно показывают направление потока данных (не вызывая дополнительную команду): < input-file command1 | command2 | command3 > output-file –  Keith Thompson 14.11.2011, 05:16
sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file

Это сначала читает файл в замене команды и производит длину самой длинной строки, (ранее, expand преобразовывает вкладки в пробелы, для преодоления семантики wc -L - каждая вкладка в строке добавит 8 вместо 1 к длине строки). Эта длина затем используется в a sed выражение, означающее ", находит строку этим количеством символов в длину, печатает его, затем выходит". Таким образом, это на самом деле может быть столь оптимально, как самая длинная строка близко к вершине файла, heheh (спасибо, освобожденное для потрясающих и конструктивных комментариев).

Другой, я думал ранее, чем sed один (в ударе):

#!/bin/bash
while read -r line; do
    (( ${#line} > max )) && max=${#line} && longest="$line"
done
echo "$longest"
5
27.01.2020, 19:36
  • 1
    Этот метод является очень дорогим и медленным. –  Chris Down 13.11.2011, 04:47
  • 2
    @Chris: Ах да это. Но вопрос был о sortest методе, не самом эффективном. Работы точно для малых и средних файлов или не критических задач, все же. –  ata 13.11.2011, 13:49
  • 3
    ПРЕДУПРЕЖДЕНИЕ: опция туалета -L, --max-line-length печатает длину самой длинной строки, согласно странице справочника, но если Вы роете глубже (как в том, когда Вы понимаете превратно / неожиданные результаты), Вы находите, что эта опция увеличивает длину 8 для каждого 1 символа вкладки \x09 посмотрите этот интересный момент Unix & Linux Q/A –  Peter.O 13.11.2011, 15:05
  • 4
    PS. Ваш ответ распечатает все "одинаково самые длинные" строки, который является, вероятно, хорошей вещью... Чтобы вынудить туалет считать только 1 символ на вкладку, это работает. sed -rn "/.{$(<file expand -t1 |wc -L)}/p" file –  Peter.O 13.11.2011, 16:13
  • 5
    read line интерпретирует оставленные из обратной косой черты символы как литеральный символ, например, \A resloves к A, который, конечно, эффективно сообщает о более коротком, чем фактическое использование байта... Для предотвращения этой завершенной интерпретации используйте: read -r line .... Кроме того, для создания sed+wc выхода версии после первой "самой длинной строки", изменения p кому: {p;q} .. sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file –  Peter.O 14.11.2011, 05:15

Следующий пример был и должен был быть, комментарий к ответу dmitry.malikov, но из-за Бесполезного Использования Видимого Пространства Комментария там, я принял решение представить его здесь, где он будет, по крайней мере, замечен...

Это - простое изменение однопроходного awk метода dmitry.
Это печатает все "равные самые длинные" строки. (Примечание. delete array расширение простофили).

awk 'length >x { delete y; x=length }
     length==x { y[NR]=$0 } END{ for (z in y) print y[z] }' file
2
27.01.2020, 19:36

В чистом ударе:

#!/bin/bash

_max_length=0
while IFS= read -r _line; do
    _length="${#_line}"
    if (( _length > _max_length )); then
        _max_length=${_length}
        _max_line=( "${_line}" )
    elif (( _length == _max_length )); then
        _max_line+=( "${_line}" )
    fi
done

printf 'Max line length: %d\n' "${_max_length}"
printf 'Lines matched with that length: %d\n' "${#_max_line[@]}"
(( ${#_max_line[@]} )) && printf '%s\n' '----------------' "${_max_line[@]}"
1
27.01.2020, 19:36
  • 1
    Как есть код может возвратить недопустимые результаты. Установка _max_line[0]=${_line} не удаляет остальную часть любой ранее накопленный короче "самые длинные строки"... unset _max_line очистит целый массив... –  Peter.O 13.11.2011, 23:00
  • 2
    @fered, спасибо за который, был записан довольно быстро. Фиксированный. –  Chris Down 13.11.2011, 23:03

Можно использовать wc:

wc -L fileName
-3
27.01.2020, 19:36
  • 1
    Считайте вопрос снова. Необходимый вывод является самой самой длинной строкой, не длиной самой длинной строки. Также посмотрите Peter. Комментарий O относительно wc -Lнедостаток. –  manatwork 01.05.2013, 14:47

Вот решение для Perl:

perl -e 'while(<>){
           $l=length;  
           $l>$m && do {$c=$_; $m=$l}  
         } print $c' file.txt 

Или, если Вы хотите распечатать все самые длинные строки

perl -e 'while(<>){
           $l=length;
           push @{$k{$l}},$_;
           $m=$l if $l>$m;
         } print @{$k{$m}}' file.txt 

Так как у меня не было ничего лучше, чтобы сделать, я работал на некоторых сравнительных тестах 625M текстовый файл. Удивительно, мое решение для Perl было последовательно быстрее, чем другие. Предоставленный, различие с принятым awk решение является крошечным, но это там. Очевидно, решения, которые печатают несколько строк, медленнее, таким образом, я отсортировал по типу, самому быстрому к самому медленному.

Распечатайте только одну из самых длинных строк:

$ time perl -e 'while(<>){
           $l=length;  
           $l>$m && do {$c=$_; $m=$l}  
         } print $c' file.txt 
real    0m3.837s
user    0m3.724s
sys     0m0.096s



$ time awk 'length > max_length { max_length = length; longest_line = $0 }
 END { print longest_line }' file.txt
real    0m5.835s
user    0m5.604s
sys     0m0.204s



$ time sed -rn "/.{$(<file.txt expand -t1 |wc -L)}/{p;q}" file.txt 
real    2m37.348s
user    2m39.990s
sys     0m1.868s

Распечатайте все самые длинные строки:

$ time perl -e 'while(<>){
           $l=length;
           push @{$k{$l}},$_;
           $m=$l if $l>$m;
         } print @{$k{$m}}' file.txt 
real    0m9.263s
user    0m8.417s
sys     0m0.760s


$ time awk 'length >x { delete y; x=length }
     length==x { y[NR]=$0 } END{ for (z in y) print y[z] }' file.txt
real    0m10.220s
user    0m9.925s
sys     0m0.252s


## This is Chris Down's bash solution
$ time ./a.sh < file.txt 
Max line length: 254
Lines matched with that length: 2
real    8m36.975s
user    8m17.495s
sys     0m17.153s
4
27.01.2020, 19:36
cat filename | awk '{ print length }' | sort -n | tail -1
7
27.01.2020, 19:36

Я тот, кто предложил изменить переменную completion-display-width readline на /r/bash , но тогда вы не указали, что она должна работать только с этой функцией завершения.

В любом случае, в функции завершения можно определить, инициируется ли она с помощью TAB (COMP_TYPE = 9) или TAB TAB (COMP_TYPE = = 63), и если это так, можно заполнить результаты мест так, чтобы они заполняли всю ширину терминала. Это наименьшая хитрость, о которой я могу думать. Это выглядело бы примерно так:

_foo_complete() {
    local i file files
    files=( ~/work/dev/jobs/"$2"* )
    [[ -e ${files[0]} || -L ${files[0]} ]] || return 0
    if (( COMP_TYPE == 63 )); then
        for file in "${files[@]}"; do
            printf -v 'COMPREPLY[i++]' '%*s' "-$COLUMNS" "${file##*/}"
        done
    else
        COMPREPLY=( "${files[@]##*/}" )
    fi
}
complete -F _foo_complete foo

На боковой ноте вы действительно не должны анализировать результаты .

-121--61942-

Ну «Linux» в основном ядро, которое вы можете скачать по адресу http://kernel.org , который обычно поставляется вместе со всеми утилитами GNU. Различные дистрибутивы, такие как Ubuntu добавить все виды программного обеспечения и некоторые инструменты упаковки. - Результат часто ошибочно называют «Linux», тоже.

Unix с другой стороны относится к целой группе различных систем: Unix history

Некоторые из них являются коммерческими, другие - бесплатными. Большинство из них имеют монолитное ядро, содержащее все стандартные инструменты, но такие инструменты, как ls , обычно не являются GNU и немного отличаются по использованию. Однако они обычно соответствуют тем же стандартам, что и POSIX .

-121--199247-

Grep первая самая длинная строка

grep -Em1 "^.{$(wc -L <file.txt)}\$" file.txt 

Команда необычайно трудна для чтения без практики, поскольку смешивает синтаксис shell- и regexp.
Для объяснения, я буду использовать упрощенный псевдокод. Строки, начинающиеся с # # , не выполняются в оболочке.
В этом упрощенном коде используется имя файла F, а для читаемости не используются кавычки и части regexps.

Как работает

Команда состоит из двух частей: grep - и wc вызов:

# # grep «^. {$ (wc -L F)} $» F

wc используется в расширении процесса, $ (...) , поэтому выполняется перед grep . Он вычисляет длину самой длинной линии. Синтаксис расширения оболочки смешивается с регулярным выражением образца синтаксисом в запутанном пути, поэтому я разложу расширение процесса:

# wc -L F
42
# grep «^. {42} $» F

Здесь расширение процесса было заменено на возвращаемое значение, создав используемую grp командную строку. Теперь мы можем читать регулярное выражение легче: Оно точно соответствует от начала ( ^ ) до конца ( $ ) строки. Выражение между ними соответствует любому символу, кроме newline, повторяемому 42 раза. Комбинированные, то есть строки, которые состоят ровно из 42 символов.


Вернитесь к реальным командам оболочки: Опция grep -E ( -extended-regexp ) позволяет не выходить за пределы {} для удобства чтения. Опция -m 1 ( -max-count = 1 ) делает его остановленным после обнаружения первой строки. < в команде wc записывает файл в свой stdin, чтобы запретить wc печатать имя файла вместе с длиной.

Какие самые длинные строки?

Чтобы сделать примеры более читаемыми с двойным именем файла, я буду использовать переменную f для имени файла; Каждый $ f в примере может быть заменен именем файла.

f="file.txt"

Показать первую самую длинную строку - первую строку, которая является самой длинной строкой:

grep -E -m1 "^.{$(wc -L <"$f")}\$" "$f"

Показать все самые длинные строки - все строки, которые длиннее самой длинной строки:

grep -E "^.{$(wc -L <"$f")}\$" "$f" 

Показать последнюю самую длинную строку - последнюю строку, которая является самой длинной строкой:

tac "$f" | grep -E -m1 "^.{$(wc -L <"$f")}\$"

Показать самую длинную строку - самую длинную строку, более длинную, чем все другие строки, или сбой:

[ $(grep -E "^.{$(wc -L <"$f")}\$" "$f" | wc -l) = 1 ] && grep -E "^.{$(wc -L <"$f")}\$" "$f" 

(Последняя команда еще более неэффективна, чем остальные, поскольку она повторяет полную команду grep. Очевидно, он должен быть разложен таким образом, чтобы выходные данные wc и строки, записанные grep , сохранялись в переменных.
Следует отметить, что все самые длинные линии на самом деле могут быть всеми линиями. Для сохранения в переменной необходимо сохранить только первые две строки.)

4
27.01.2020, 19:36

Я разработал небольшой сценарий оболочки для этого. Он отображает длину, строку # и саму строку по длине, которая превышает определенный размер, например 80 символов:

#!/bin/sh

# Author: Surinder

if test $# -lt 2
then
   echo "usage: $0 length file1 file2 ..."
   echo "usage: $0 80 hello.c"
   exit 1
fi

length=$1

shift

LONGLINE=/tmp/longest-line-$$.awk

cat << EOF > $LONGLINE
  BEGIN {
  }

  /.*/ {
    current_length=length(\$0);
    if (current_length >= expected_length) {
       printf("%d at line # %d %s\n", current_length, NR, \$0);
    }
  }

  END {
  }
EOF

for file in $*
do
  echo "$file"
  cat $file | awk -v expected_length=$length -f $LONGLINE |sort -nr
done

rm $LONGLINE

https://github.com/lordofrain/tools/blob/master/longest-line/longest-line.sh

0
27.01.2020, 19:36

Это решение с использованием Python

python -c 'import sys;print(max(open(sys.argv[1],"r").readlines(), key=len))' file.txt
0
10.07.2020, 14:42

Теги

Похожие вопросы