Ganti konten grup regex capture menggunakan sed


16

Saya mencoba mengedit file nginx.conf saya secara terprogram, yang berisi baris seperti ini:

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

yang saya ingin terlihat seperti ini:

        access_log /dev/stdout;

Saya percaya regex ^\s*access_log([^;]*);akan menangkap /var/log/nginx/access.logbagian dalam grup tangkap, tapi saya tidak yakin bagaimana cara benar mengganti kelompok tangkap dengan sed?

Saya sudah mencoba

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

tapi saya mendapatkan kesalahan:

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

jika saya coba sed -rmaka tidak ada kesalahan, tetapi hasilnya tidak seperti yang saya harapkan:

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

Saya mencoba menjadi pintar dengan grup tangkap dan yang lainnya dan tidak mencari langsung "access_log /var/log/nginx/access.log;" dalam hal distribusi mengubah lokasi file log default.


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

@ Costas Jika Anda mau menjawabnya, saya akan mendukung Anda karena itu juga berhasil!
Abe Voelker

Jawaban:


16

Beberapa kesalahan di sana.

Pertama, karena sedmenggunakan ekspresi reguler dasar, Anda perlu \(dan \)membuat grup tangkap. The -rberalih memungkinkan diperpanjang ekspresi reguler yang mengapa Anda tidak mendapatkan kesalahan. Lihat Mengapa saya perlu keluar dari karakter regex di sed untuk diartikan sebagai karakter regex? .

Kedua, Anda menempatkan kelompok penangkap di tempat yang salah. Jika saya memahami Anda dengan benar, Anda dapat melakukan ini:

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

Perhatikan penggunaan !sebagai pembatas regex untuk menghindari keharusan melepaskan garis miring ke depan /dev/stdout.


Terima kasih, bekerja dengan luar biasa! Saya belum dapat menandai ini sebagai diterima, tetapi akan kembali dalam 9 menit untuk melakukannya.
Abe Voelker

1
@AbeVoelker Terima kasih. Aku senang bisa membantu.
Joseph R.

5

Di regexp Anda, Anda harus tahu bahwa itu \No.adalah referensi kembali ke pola di dalam tanda kurung (). Jadi regexp seharusnya's@^(\s*access_log ).*$@\1/dev/stdout/;@'

Saya bisa menawarkan

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

PETUNJUK: Apakah Anda bermaksud untuk menggunakan /di dalam patern Anda bebas untuk mengubah s///untuk setiap simbol yang Anda inginkan s###misalnya


Terima kasih, saya berharap dapat menerima dua jawaban! Saya tidak lagi menyesal tidak sepenuhnya membaca halaman manual sebelum meminta bantuan setelah melihat solusinya.
Abe Voelker

3

Daripada menangkapnya, mengapa tidak mencari saja dan melakukan substitusi? Yaitu:

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

Ia mencari garis yang cocok dengan " access_log" lalu pada garis apa pun yang melakukannya akan menggantikan " /whatever/path/is/there;" dengan " /dev/stdout;"

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.