2012-01-29 28 views
17

Belirli bir desenle eşleşen olmayan bir alt dizeyi bulmak için doğru sözdizimi (belirli bir dizeden önce gelen ve sonra gelen dizeler) nedir?Sed regex ve substring negation

Örneğin, BEGIN_ ile başlangıç ​​tüm alt dizeleri, _END ucunu ve değil eşit FOO için aradaki substring almak; ve tüm alt dizgeyi "(iç alt dizgi)" biçiminde değiştirin. Aşağıdaki eşleşir:

  • BEGIN_bar_END ->(bar)
  • BEGIN_buz_END ->(buz)
  • BEGIN_ihfd8f398IHFf9f39_END ->(ihfd8f398IHFf9f39)

Ama BEGIN_FOO_END maç olmaz.

Ben aşağıda etrafında oynamıştır ama doğru sözdizimi bulmak gibi olamaz: DFAs için olumsuzlama ile regexes derleme üstel zaman alır, çünkü

sed -e 's/BEGIN_(^FOO)_END/($1)/g' 
sed -e 's/BEGIN_([^FOO])_END/($1)/g' 
sed -e 's/BEGIN_(?!FOO)_END/($1)/g' 
sed -e 's/BEGIN_(!FOO)_END/($1)/g' 
sed -e 's/BEGIN_(FOO)!_END/($1)/g' 
sed -e 's/BEGIN_!(FOO)_END/($1)/g' 
+0

, bu 'kullanılarak elde edilebilir':! Http://www.grymoire.com/Unix/Sed.html#uh-32 – Zenexer

cevap

27

Sed, IIRC hiçbir genel olumsuzluk operatörü vardır. /BEGIN_FOO_END/b demektir nerede

'/BEGIN_FOO_END/b; s/BEGIN_\(.*\)_END/(\1)/g' 

ile bu çalışabilirsiniz: Biz BEGIN_FOO_END bulursak, o zaman şube (atlama) Sed komut sonuna.

+9

da "sed" yazılabilir/BEGIN_FOO_END /! S/BEGIN _ \ (. * \) _ END/(\ 1)/g ' – potong

+2

' sed '/ BEGIN_FOO_END /! S | BEGIN_ \ not etmek isterim (.* \) _ END | (\ 1) | g '' çalışıyor ama 'sed' | BEGIN_FOO_END |! S | BEGIN _ \ (. * \) _ END | (\ 1) | g 'değil! Açıkça, ikinci bölümde "/" den farklı bir ayırıcı değiştirmenizi sağlar, ancak ilk bölümde değil. Tuhaf. – CommaToast

+1

@CommaToast /// 'komutu, keyfi bir sınırlayıcı kullanabilir; adresler yapamaz. – TheDudeAbides

2

Ben güzel bir yol bilmiyorum, ama her zaman yapabilirsiniz: tek dize varsa

sed 'h;s/BEGIN_\(.*\)_END/(\1)/;/^(FOO)$/g' file 

Bu yalnızca işleri:

$ cat file 
BEGIN_FOO_END 
BEGIN_FrOO_END 
BEGIN_rFOO_END 
$ sed '/BEGIN_FOO_END/ !{s/BEGIN_\([^_]*\)_END/(\1)/}' file 
BEGIN_FOO_END 
(FrOO) 
(rFOO) 
3

Bu sizin için işe yarayabilecek satır başına. Satır başına birden dizeleri için

:

sed 's/BEGIN_\([^F][^_]*\|F[^O][^_]*\|FO[^O][^_]*\|FOO[^_]\+\)_END/\(\1\)/g' file 

Ya da daha kolay anlaşılır:

sed 's/\(BEGIN_\)FOO\(_END\)/\1\n\2/g;s/BEGIN_\([^\n_]*\)_END/(\1\)/g;s/\n/FOO/g' file