sed, wzorce niepasujące

Posted on Fri 24 September 2004 in Tips text {sed, awk, perl, etc.}

Mam losowy łańcuch znaków, w którym interesuje mnie pewien element. Potrafię opisać go wyrażeniem regularnym. Jak teraz usunąć wszystko to, co nie pasuje do wyrażenia? Załóżmy, że interesuje mnie foo: echo losowyłańcuchfoobarshmoo | sed 's/foo//' usunie foo, podczas gdy ja chcę, by tylko foo pozostało. Kombinowałem trochę z !, ale nie wiem jak to zastosować.


sed 's/.*\(foo\).*/\1/'
To się chyba "backreferences" nazywa. Bierzesz coś w nawiasy \(...\),
a potem się możesz do tego odwoływać przez \1, \2 itp., w zależności o którą parę nawiasów Ci chodzi (można poszatkować regexp na kawałki, usunąć wybrane fragmenty, zamienić ich kolejność, zduplikować je itp.). Np załóżmy, że masz listę wierszy w postaci:
a=b+c
a chcesz je pozamieniać na
a-c=b
więc robisz 's/\(.*\)=\(.*\)+\(.*\)/\1-\3=\2/g'
Działa cacy. Albo inny przykład - chcesz wygenerować szybki indeks html
mając tylko płaski spis plików (np. wynik "ls").
track01.cdda.ogg
track02.cdda.ogg
track03.cdda.ogg
track04.cdda.ogg
track05.cdda.ogg
track06.cdda.ogg
Więc można to przepuścić przez:
's/^\(.*\)\.cdda\.ogg$/<a href="&">\1<\/a>/g'
i już masz spis html-owych odnośników, z odciętymi rozszerzeniami.


Jesteś tego absolutnie pewien? Skąd to przeświadczenie, że wszyscy używają Extended RE? Mój sed na przykład standardowo pracuje w trybie Basic RE i jeśli zastosowałbym się do Twoich "poprawek", to wszystko bym popsuł.