Як шукати текст у файлі, ігноруючи нові рядки?


11

Я хотів би знайти текст, який може бути розділений на кілька рядків у файлі. Греп, який ігнорує розриви рядків та повертає відповідні проміжки рядків.

наприклад, я б шукав is an example file, і очікую, що він буде знайдений у наступному файлі:

Це приклад файл.

Не залежати від провідних чи кінцевих просторів, повністю ігноруючи всі форми білого простору, можливо, найкраще (в ідеалі трактувати будь-яку послідовність білого простору як єдиний простір).


Одне неідеальне рішення полягає в тому tr '\n' ' ' | grep, що розмежовує матчі та невідповідні, але не показує відповідність, а також не працює з великими файлами.


на SO (немає остаточної відповіді): stackoverflow.com/q/1858312/1449460
Nikana Reklawyks

Як зауваження, пошук emacs, здається, справляється із цією справою ( isearch-forward)
Нікана Реклавікс

Так само Вім - х: /This\_sis. Для отримання більш докладної інформації: :help \_s.
lcd047

Додайте цей рядок в кінці рядка пошуку: tr -n "\ n" Це видалить усі нові рядки. Сподіваюся, що це допоможе!
Ден Хоуел

Відповіді:


12

ГНУ grepможе це зробити

grep -z 'is\san\sexample\sfile.' file

Щоб виконати деякі моменти, що виникають у коментарях, існують деякі модифікації сценарію:

 grep -oz '^[^\n]*\bis\s*an\s*example\s*file\.[^\n]*' file

Щодо величезних файлів, я не маю уяви щодо обмеження пам’яті, але у випадку проблеми ви можете вільно користуватися sed

sed '/\bis\b/{
          :1
          N
          /file\.\|\(\n.*\)\{3\}/!b1
         }
     /\<is\s*an\s*example\s*file\./p
     D' file

які зберігають у пам'яті не більше 4-х рядків (бо 4 слова в шаблоні \(\n.*\)\{3\}).


5
Наскільки я впевнений, ви знаєте, що -zопція пропонує grepтрактувати нові рядки як звичайні текстові символи та шукати нульові байти, щоб розділити записи. У текстовому файлі без нульових байтів (тобто типовий випадок) grep -zбуде розглядатись весь файл як один рядок. Отже (1) виникає питання про те, наскільки добре він може обробляти великі файли, і (2) якщо він знайде збіг, він випише весь файл, не даючи підказки щодо місця відповідності. Також (3) в ОП сказано: "В ідеалі - трактування будь-якої послідовності пробілу як єдиного простору", тому вам слід використовувати \s+та додавати -E.
G-Man каже: "Відновіть Моніку"

1
@ G-Man Дякую за коментар. Будь ласка, дивіться відредаговану відповідь.
Костас

1
(0) Ах -o; Я про це забуваю. Розумний спосіб його використання. (1) Ваша нова grepвідповідь починається ^[\n]*; це друкарня для [^\n]*. (2) я сказала \s+навмисно.  be\s*littleбуде відповідати belittle, і care\s*lessбуде відповідати careless. Але я думаю, це незначна проблема. І, якщо ви не хочете використовувати -E, ви можете використовувати «версію бідної людини» з \s+, а саме \s\s*. (3) Приємна sedкоманда. Він може вийти з ладу, якщо є порожні рядки (тому чотирисловна фраза може поширюватися на більше ніж чотири рядки); Я зміг це виправити, додавши s/\n\s*\n/\n/.
G-Man каже: "Відновіть Моніку"

@ G-Man Спасибі вам Ваші коментарі дуже корисні. Я намагаюся розмістити більш-менш портативний код, тому що відомі члени кожного разу підштовхують мене до цього. У будь-якому випадку навіть без -Eвас сталь зможе використовувати +у \s\+формі. Порожні рядки всередині візерунка здаються надуманими.
Костас

Я думав сторінкові текстові документи, як РЛК - Істр , що сторінки людини схожі , що на деяких системах (або робив ) - але при подальшій думки, що відбувається зі мною , що більшістю таких документів мають заголовок сторінки (и) та / або нижній колонтитул (ів), які потрібно викреслити, перш ніж ви зможете сподіватися на grepних фрази.
G-Man каже: "Відновіть Моніку"

7

Спробуйте це:

pcregrep -M '\bThis\s+is\b' <<EOT
This
is
an example
file.
EOT

Чи потрібно вводити \s5 разів, якщо я шукаю "це дуже довгий зразок"?
Nikana Reklawyks

1
Так: справа - це \sпробіли, а нова лінія - це "пробіл".
lcd047

Я маю на увазі, що робити, якщо файл є This\nis a very\nlong pattern, і я не знаю, де можуть відбуватися розриви рядків. Мені доведеться шукати This\sis\sa\svery\slong\spattern, правда? (що стає стомлюючим, коли довжина візерунка збільшується або наклеюється з інших місць)
Nikana Reklawyks

2
Тоді ви робите це так: pcregrep -M "$( echo 'This is a very long pattern' | sed 's/ /\\s+/g' )" file.
lcd047
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.