grep --before-context 5
показує 5 рядків перед матчем.
Хочу показати все перед матчем.
Робити це grep --before-context 99999999
буде добре, але це не дуже ... професійно.
Як показати весь файл до відповідності?
grep --before-context 5
показує 5 рядків перед матчем.
Хочу показати все перед матчем.
Робити це grep --before-context 99999999
буде добре, але це не дуже ... професійно.
Як показати весь файл до відповідності?
Відповіді:
Sed краще для цього.
Просто зробіть:
sed '/PATTERN/q' FILE
Це працює так:
Для кожного рядка ми дивимось, чи відповідає /PATTERN
:
Це найефективніше рішення, адже як тільки воно бачить PATTERN
, воно припиняється. Без цього q
sed продовжував би читати решту файлів і нічого не робити з цим. Для великих файлів це може змінити значення.
Цей трюк також можна використовувати для наслідування head
:
sed 10q FILE
sed '/PATTERN/Q' FILE
буде пропущена відповідна лінія. Q
є розширенням GNU, тому він не працюватиме з будь-яким sed.
sed
може замінити більшість функцій grep.
sed -n '1,/<pattern>/ p' <file>
Це означає, що друкуємо з першого рядка, поки візерунок не збігається.
Кілька прикладів діапазону
sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2
друкувати до та включати відповідність:
awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename
друкувати до НЕ, включаючи відповідність:
awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
Q
Класний, але специфічний афаік, sed -n '/pattern/!p;//q'
був би більш портативним.
!
це p
стосується рядків, які не відповідають pattern
, але потім //q
мене бентежить ...
//
означає "попередній регулярний вираз" (я вважав, що це означає "відповідати порожній рядку"). Я думаю , що більш короткий варіант того ж розчину: sed -n '/pattern/q;p
?
Наступні чисті grep
методи GNU неефективні.
Шукайте все до першого примірника рядка " foo " на панелі файлів , використовуючи три grep
s:
grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar
Відповідність до останньої інстанції " foo ":
grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar
Примітка: детальну інформацію про останню grep
можна знайти в: Regex (grep) для пошуку в рядках .
grep
s (+ pcre), коли справа в тому, щоб просто запустити одне sed
виклик: sed 'x;/./G;//!x;/foo/p;//s/.*//;x;d'
??
sed
код здається вартим власної відповіді, або його можна додати до одного з інших. Re 7 grep
s: Тому що grep
відповіді не було ... (плюс, відповідь допомагає показати, чому ні.)
Додавання відповіді Мікеля вище ...
Щоб надрукувати всі рядки до, але не включаючи першого рядка, FILE
що містить PATTERN
, спробуйте:
sed '/.*PATTERN.*/{s///;q;}' FILE
Це відповідає всій лінії, що містить шаблон, замінює його порожнім рядком, а потім виходить, не обробляючи решту файлу.
Пост-сценарій:
Найпростіший / найясніший спосіб, який я міг придумати, щоб запобігти друку додаткового нового рядка наприкінці (без залучення іншого інструменту), було запустити sed і знову видалити новий заключний рядок:
sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'
... а оскільки ми все-таки видаляємо цей рядок, наша попередня робота є зайвою, і ми можемо спростити:
sed '/PATTERN/q' FILE | sed '$d'
sed
виклику.
tcsh
у bash
псевдонімі, так і потрібно було переконатися, що я мав відносно стисле однолінійне рішення, яке працювало як у стандартному, так і в GNU sed
(для мобільності); всі вимоги, які ваш внесок, можливо, дуже добре виконали. Як хтось, хто sed
дуже рідко використовує , найголовнішою моєю вимогою було те, що я міг швидко зрозуміти, коли хочу легко редагувати чи повторно призначити це через роки.
Для людей, які вирішили запам'ятати лише основні інструменти у щоденній роботі та готові прийняти менш елегантні та менш ефективні рішення:
head -n $(grep -n pattern filename | cut -d: -f1) filename
Якщо ця команда призначена для сценарію, я буду шукати більш елегантні (і, можливо, ефективні) рішення. Якщо це одноразова команда або сценарій викидання, то мені все одно.
Ви також можете скористатися одним із наступних
tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac
або
tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac
або
tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac
Перший варіант дуже схожий на те, що запропонував ОП, тільки він гарантує, що ти покажеш достатньо рядків перед контекстом, підрахувавши рядки у файлі
Другий варіант шукає номер рядка першого збігу (ви також можете змінити це, змінивши внутрішню "голову"), а потім використовує заголовок цього номера
Останній варіант замінює всі нові рядки на відповідність, а потім замінює два суміжні збіги новим рядком. Результатом цього є рядок для кожного блоку тексту між двома збігами. Після цього він використовує 'head' для вибору першого рядка (переміщення блоку тексту до першого співпадіння), а потім повторно переводить кожний матч у новий рядок. ця опція працює лише у тому випадку, якщо файл у наступному форматі
pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern
texttexttext
texttexttexttexttexttexttexttexttext
і так далі
sed
команда внизу є начебто загальною.