menggunakan sed dengan ampersand (&)

19

Saya menggunakan sed untuk menemukan dan mengganti pola dalam file SAS yang saya miliki daripada mengubahnya secara individual. Masalahnya adalah saya mencoba mengganti variabel makro dan ketika saya menggunakan ampersand tidak diproses dengan benar.

Here's my code:
sed -ie 's/user=&uid./user=&sysuserid./g' *_table_*.sas

setiap kali saya menjalankan perintah ini sepertinya menambahkan dan melakukan segala macam hal funky dengan teks asli.

Pertanyaan: Bagaimana cara mengganti teks yang berisi ampersand dengan perintah sed?

lucasdavis500
sumber
6
&adalah karakter khusus sehingga harus diloloskan ketika digunakan dalam RHS - dalam kasus Anda, Anda harus menjalankan 's/user=&uid./user=\&sysuserid./g'meskipun saya menduga Anda juga perlu melarikan diri dari titik di LHS untuk mencocokkan titik literal sehingga Anda benar-benar perlu's/user=&uid\./user=\&sysuserid./g'
don_crissti
1
ya, '&' di sebelah kanan pada dasarnya berarti "segala sesuatu yang cocok di sebelah kiri", jadi lepaslah dengan '\'. Anda harus menjawabnya, bukan hanya komentar.
Edward Falk
saya tidak perlu melarikan diri dari periode pertama ... hanya ada orang-orang yang penasaran :)
lucasdavis500

Jawaban:

25

&khusus dalam teks pengganti: itu berarti "seluruh bagian dari input yang cocok dengan pola", jadi apa yang Anda lakukan di sini diganti user=&uidXdengan user=user=&uidXsysuserid.. Untuk memasukkan ampersand yang sebenarnya dalam teks pengganti, gunakan \&.

Hal lain yang terlihat salah adalah bahwa .dalam pola pencarian berarti karakter apa pun (kecuali baris baru), tetapi .pada akhir teks pengganti adalah titik literal. Jika Anda ingin mengganti hanya string literal user=&uid., lindungi .dengan backslash.

sed -e 's/user=&uid\./user=\&sysuserid./g'

Jika Anda ingin mengganti salah satu karakter dan menyimpannya dalam hasilnya, masukkan karakter ke dalam grup dan gunakan \1dalam pengganti untuk merujuk ke grup itu.

sed -e 's/user=&uid\(.\)/user=\&sysuserid\1/g'

Bahkan, mengingat pengulangan antara teks asli dan penggantian, Anda harus tetap menggunakan grup:

sed -e 's/\(user=&\)u\(id\.\)/\1sysuser\2/g'

yaitu "ganti udengan sysuserantara user=&dan id.".

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Bisakah Anda menjelaskan kelompok?
lucasdavis500
2
@ lucasdavis500 Grup mengidentifikasi bagian dari pola. Ini dibatasi oleh tanda kurung backslash. Misalnya \(user=&\)adalah pola yang cocok user&dan menyimpan string yang cocok sebagai grup (nomor grup 1 karena itu adalah kelompok pertama dalam pola). Kemudian dalam penggantian \1digantikan oleh string yang disimpan untuk nomor grup 1.
Gilles 'SO- stop being evil'
maksud Anda (pengguna = &) menyimpan pengguna = &, bukan pengguna &?
lucasdavis500
@ lucasdavis500 Saya tidak mengerti komentar Anda. Karakter =dalam ekspresi reguler dan dalam teks pengganti adalah singkatan dari dirinya sendiri, jadi user=&hanya cocok user=&, dan user=&dalam teks pengganti menghasilkan user=diikuti oleh bagian dari baris yang cocok dengan regex.
Gilles 'SANGAT berhenti menjadi jahat'
1
@ lucasdavis500 =Karakter tidak memiliki arti khusus. user=&dalam teks pengganti menghasilkan user=diikuti oleh teks yang cocok asli. user=\&dalam teks pengganti menghasilkanuser=&
Gilles 'SO- stop being evil'