Шукайте рядок і друкуйте все до і після в межах діапазону


9

У мене є цей файл:

sometext1{
string1
}

sometext2{
string2
string3
}

sometext3{
string4
string5
string6
}

Я хочу шукати в цьому файлі певний рядок і надрукувати все перед цим рядком до відкриття {і все після цього рядка до закриття }. Я намагався досягти цього за допомогою sed, але якщо я спробую надрукувати все в діапазоні, /{/,/string2/наприклад, sed роздруковує це:

sometext1{
string1
}

sometext2{
string2
sometext3{
string4
string5
string6
}

Якщо я шукаю рядок "string2", мені потрібен вихід:

sometext2{
string2
string3
}

Дякую.


Ну, тепер я виявив, що мені потрібні номери рядків вихідного файлу в оригінальному файлі, щоб потім їх видалити. Я спробував змінити команду, яку подав @mikeserv не пощастило, я трохи заплутався у функції утримування sed.
rodrigo

ну, боже, родріго, ти цього не сказав нікому, крім себе. це можна зробити, але найкраще робити так grep -n '' <infile | sed .... Ці sedкоманди будуть потрібні зміну; зокрема біти /адреси, /які шукають ^якісні якірні елементи. Таким чином, якщо ви використовували мій відповідь, ймовірно , можна зробити наступне : grep -n '' | sed 'H;/{$/h;/^[^:]*:}/x;/{\n.*PATTERN/!d'. Усі вихідні рядки будуть встановлені з префіксами номерів рядків оригінального файлу з подальшим двокрапкою тощо 1:sometext1{\n2:string1. sedбуде фільтрувати лише те, що фільтрувалося б раніше, за винятком того, що кожен вихідний рядок відкривається цифрою.
mikeserv

Відповіді:


9

Ось дві команди. Якщо ви хочете команду, яка обробляє до останнього .*{$рядка в послідовності (як це робить @don_crissti ed), ви можете зробити:

sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'

... що працює, додаючи кожен рядок до Hстарого простору слідом за \nсимволом ewline, перезаписуючи hстарий пробіл для кожного рядка, який відповідає {$, та замінюючи hстарі пробіли та шаблони для кожного рядка, який відповідає ^}- і тим самим промиває його буфер.

Він друкує лише рядки, які відповідають {тодішній \nлінії ewline, а потім PATTERNв якийсь момент, і це відбувається лише одразу після зміни буфера.

Він виводить будь-які рядки в серії {$збігів до останнього в послідовності, але ви можете отримати всі ці включно, такі як:

sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'

Що робиться - це схема заміни та hстарі пробіли для кожної ...{$.*^}.*послідовності, додає всі рядки в послідовності до Hстарого простору за \nсимволом ewline та Dвибирає до першого \nсимволу ewline у ​​просторі шаблону для кожного циклу рядків, перш ніж знову починати з того, що залишається.

Звичайно, єдиний раз, коли він коли-небудь отримує \newline в просторі шаблону, це коли рядок введення збігається ^}- кінець вашого діапазону - і тому, коли він повторює сценарій у будь-якому іншому випадку, він просто перетягується в наступний рядок вводу, як правило.

Коли PATTERNвиявляються в тому ж шаблоні , як \newline, хоча, він друкує багато перед перезаписом його ^}знову (так що він може закінчити коло і очистити буфер) .

Враховуючи цей вхідний файл (спасибі Дон) :

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
}

Перші відбитки:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}

... і друге ...

sometext2{
PATTERN
string3
}
Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}

@don_crissti - я не знаю. Це лише розмежовує послідовність рядка, що починається з }. Це може бути корисним для подібних ... open{\nsub;\n{ command; }\n}; close- але я не впевнений, що тут відбувається ...
mikeserv

Привіт @mikeserv - У мене є подібне питання, яке тут піднімається unix.stackexchange.com/questions/232509/… , ваше рішення працює на невеликому файлі, але у мене є великий файл, і я отримую "Затримка простору заповнена". повідомлення про помилку. Чи знаєте ви будь-який шанс, як я міг це вирішити? Велике спасибі
Нараян Ахаде

@NarayanAkhade - ні. не обійшлося без капітального ремонту. хіба що ... чи є великі простори вводу, які не містять {...}блоків? Якщо це так, і ви використовуєте перше рішення, тоді ви можете зробити це /{$/,/^}/Hна початку, а не просто H. Але якщо ви також спробували друге рішення і все-таки зіткнулися з тією ж помилкою, це, швидше за все, не допоможе, тому що це вже робить. І не знижуйте ed. Тут не дуже хороша відповідь, і він edможе бути застосований до використання тимчасових буферних файлів також дуже просто, що повинно запобігати перевищенню буфера пам'яті.
mikeserv

6

Ось рішення з ed:

ed -s filename <<< $'g/PATTERN/?{?,/}/p\nq\n'

це є:

g/PATTERN/     # mark each line matching PATTERN  
?{?,/}/p       # for each marked line, print all lines from the previous { up to the next }  
q              # quit editor

Це передбачає, що PATTERNміж кожною парою є лише один рядок, { }інакше ви отримаєте повторюваний вихід для кожного додаткового рядка з PATTERNодним і тим же блоком.
Він буде працювати для декількох, { }що містять відповідність одного рядка, PATTERNнаприклад, для тестового файлу з PATTERNдвома різними розділами:

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
}

біг

ed -s sample <<< $'g/PATTERN/?{?,/}/p\nq\n'

Виходи:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN again

another string here
}

Насправді я багато взяв із цього! Дуже дякую!
mikeserv

Я навіть не знаю, що ця команда існує. Спасибі
rodrigo

4

З pcregrep:

pcregrep -M '(?s)\{[^}]*PATTERN.*?\}'

Або з GNU за grepумови, що вхід не містить балів NUL:

grep -Poz '.*(?s)\{[^}]*PATTERN.*?\}'

0
$ awk 'BEGIN{RS="\n\n"; FS="[{}]"} {if ($2 ~ /string4/) {print $2}}' t1.txt
string4
string5
string6

де:

  • string4 -> рядок, який повинен відповідати
  • t1.txt -> містить вміст файлу, згаданий у запиті

-2

sed -n '/ string / p' ім'я файлу

-n при додаванні до поведінки за замовчуванням sed придушений sed це твердження може не дати тобі саме те, що ви хочете, але він повинен просто змістити рядок

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.