Regex yakalama grubu içeriğini sed kullanarak değiştirme


16

Böyle bir satır içeren programlı, nginx.conf dosyasını düzenlemeye çalışıyorum:

        access_log /var/log/nginx/access.log;

ki şöyle görünmek istiyorum:

        access_log /dev/stdout;

Normal ifadenin bir yakalama grubundaki parçayı ^\s*access_log([^;]*);yakalayacağına inanıyorum /var/log/nginx/access.log, ancak yakalama grubunu sed ile nasıl doğru bir şekilde değiştireceğimi bilmiyorum?

denedim

echo "        access_log /var/log/nginx/access.log;" | sed 's/^\s*access_log([^;]*);/\1\\\/dev\\\/stdout/'

ama hatayı alıyorum:

sed: -e expression #1, char 45: invalid reference \1 on `s' command's RHS

denerseniz sed -ro zaman hata yok, ama çıktı beklediğim gibi değil:

 /var/log/nginx/access.log\/dev\/stdout

Yakalama grubu ve whatnot ile akıllı olmaya çalışıyorum ve doğrudan "access_log /var/log/nginx/access.log;" dağıtımın varsayılan günlük dosyası konumunu değiştirmesi durumunda.


1
sed '/access_log/s|/[^;]\+|/dev/stdout|'
Costas

@Costas Bu cevabı verirseniz, aynı zamanda işe yarayacağından sizi oylarım!
Abe Voelker

Yanıtlar:


16

Orada birkaç hata var.

İlk olarak, sedtemel düzenli ifadeler kullandığından, bir yakalama grubu yapmanız \(ve yapmanız gerekir \). -rAnahtar Hatayı alamadım neden olan normal ifadeler genişletilmiş etkinleştirir. Bkz Ben düzenli ifade karakterleri olarak yorumlanmalıdır sed regex karakterlerden kurtulmak gerekiyor Neden? .

İkincisi, yakalama grubunu yanlış yere koyuyorsunuz. Seni doğru anlarsam, bunu yapabilirsiniz:

sed -e 's!^\(\s*access_log\)[^;]*;!\1 /dev/stdout;!' your_file

Kullanımına dikkat !ileri eğik çizgi kaçış zorunda kalmamak için regex sınırlayıcı /dev/stdout.


Teşekkürler, harika çalışıyor! Bunu henüz kabul edilmiş olarak işaretleyemiyorum, ancak bunu yapmak için 9 dakika içinde döneceğim.
Abe Voelker

1
@AbeVoelker Çok hoş geldiniz. Yardımcı olabileceğim için mutluyum.
Joseph R.

5

Normal ifadenizde \No., parantez içindeki desene geri başvuru olduğunu bilmelisiniz (). Yani normal ifade olmalı's@^(\s*access_log ).*$@\1/dev/stdout/;@'

önerebilirim

sed '/access_log/s|/[^;]\+|/dev/stdout|'

İPUCU: İster /paternin içinde kullanmak isteyin, örneğin s///istediğiniz her sembol için değiştirmekte özgürsünüzs###


Teşekkürler, iki yanıtı kabul edebilsem! Artık çözümleri gördükten sonra yardım istemeden önce man sayfalarını tam olarak okumadığım için pişman değilim.
Abe Voelker

3

Yakalamak yerine, neden sadece onu bulup yerine koymuyoruz? yani:

sed "/access_log/ s| /.*;| /dev/stdout;|"

" access_log" İle eşleşen satırları arar ve bunu yapan tüm satırlarda " /whatever/path/is/there;" ile " /dev/stdout;"

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.