2010-03-25 2 views
2

Как я могу сделать переопределение регулярных выражений sed во всем тексте, который предшествует строке, соответствующей регулярному выражению.Используя sed и/или awk, как можно сделать привязку sed по всему тексту в файле, пока не увижу строку, соответствующую регулярному выражению?

например. Как я могу сделать своп как этого

s/foo/bar/g 

для всего текста, который предшествует первый пункт это регулярное выражение соответствует:

m/baz/ 

Я не хочу использовать positive/negative look ahead/behind в моем SED регулярного выражения, потому что те действительно дорогостоящие операции над большими файлами.

+0

Я предполагаю, что из вашего упоминания опережающего просмотра/за что вы имеете в виду первую точку в каждой строке, которая соответствует, а не первая точка в файле? Но остальная часть фразы не согласуется с этим ... было ли обратное отношение к сопоставлению шаблонов во всем файле вместо строки за строкой? – Cascabel

+0

Я говорил о полном файле. Я не знал, что sed работал по строкам. –

ответ

4

Если вы имеете в виду, что вы хотите сделать замену на каждой строке предыдущей данный матч, это ваш ответ:

Замещение принимает необязательный адрес диапазон; вы можете использовать оба числа и шаблоны. В этом случае, начиная с линии 1, идти до вашего шаблона:

sed '1,/baz/s/foo/bar/g' 

В AWK:

awk ' 
/baz/ { done = 1 } 
{ 
    if (!done) { 
     gsub(/foo/, "bar") 
    } 
    print 
}' 

(Это действительно достаточно коротким, чтобы оставить вне разрывы строк, но они делают его доступным для чтения)

+0

Вы можете заметить, что вы не можете делать '1,/baz/-1s/foo/bar /'. –

+0

@ Джонатан: Это очень хороший момент. Если вы хотите не касаться линии, где/baz/match, это очень сложно в sed, но awk все равно сможет это сделать. – Cascabel

+0

и ваше решение изменит «foo» на «bar», если «baz» не найден – ghostdog74

3
$ cat file 
123 abc 01 
456 foo 02 bar 
789 ghi 
baz 
blah1 
blah2 
foo bar 

$ awk -vRS="baz" 'NR==1{gsub("foo","bar")}1' ORS="baz" file 
123 abc 01 
456 bar 02 bar 
789 ghi 
baz 
blah1 
blah2 
foo bar 
baz 

использовать разделитель записи «baz», после чего первой записью будет запись, которую вы хотите изменить «foo» на «bar».

с SED, изменение решения Денни, чтобы заботиться о «БАЗ» в первой строке

sed '0,/baz/{/baz/!s/foo/bar/g}' file 
4

Это вариация на ответ Jefromi должен сделать трюк, не касаясь линии, что «Баз» на появляется как указано в Комментарий Джонатана.

sed '1,/baz/{/baz/!s/foo/bar/g}' 
+0

Вау, я должен был подумать об этом.Я уже думал обо всем этом ерунде, читающем следующую строчку в ... +1. – Cascabel

1

Это может работать для вас:

awk '/baz/{p=1};!p{gsub(/foo/,"bar")};1' file 

или это:

sed '/baz/,$!s/foo/bar/g' file