Переконайте перший найдовший рядок
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) дозволяє не уникати значення {}для читабельності. Опція -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були збережені до змінних.
Зауважте, що всі найдовші рядки насправді можуть бути усіма рядками . Для збереження змінної потрібно зберігати лише перші два рядки.)