Grep первая самая длинная линия
grep -Em1 "^.{$(wc -L <file.txt)}\$" file.txt
Команда необычно трудна для чтения без практики, потому что она смешивает синтаксис оболочки и регулярных выражений.
Для объяснения я сначала буду использовать упрощенный псевдокод. Строки, начинающиеся с ##
, не запускаются в оболочке.
Этот упрощенный код использует имя файла 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
) останавливает ее после того, как найдена первая строка. Команда <
in wc
записывает файл в его стандартный ввод, чтобы предотвратить 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
, сохранялись в переменные.
Обратите внимание, что все самые длинные строки могут фактически быть всеми строками Для сохранения в переменной необходимо сохранить только первые две строки.)