Apa cara yang baik untuk melakukan penggantian string dalam file menggunakan kamus dengan banyak pasangan substituen-substituen? Dan dengan banyak , maksud saya sebenarnya sekitar 20 – tidak banyak, tetapi cukup banyak sehingga saya ingin mengaturnya dengan rapi.
Saya agak ingin mengumpulkan semua pasangan substituen-substituen dalam file dictionary.txt
dengan cara yang mudah dikelola, karena saya perlu mengganti banyak hal, katakan seperti:
"yes" : "no"
"stop" : "go, go, go!"
"wee-ooo" : "ooooh nooo!"
"gooodbye" : "hello"
"high" : "low"
"why?" : "i don't know"
Sekarang saya ingin menerapkan substitusi ini di beberapa file novel.txt
.
Lalu saya ingin menjalankan magiccommand --magicflags dictionary.txt novel.txt
sehingga semua contoh yes
di novel.txt
diganti dengan no
(bahkan Bayesian
akan diganti dengan Banoian
) dan semua contoh goodbye
di novel.txt
akan diganti dengan hello
dan seterusnya.
Sejauh ini, string yang perlu saya ganti (dan ganti dengan) tidak memiliki tanda kutip (tidak tunggal atau ganda) di dalamnya. (Akan lebih baik, meskipun, untuk melihat solusi bekerja dengan baik dengan string yang berisi tanda kutip, tentu saja.)
Saya tahu sed
dan awk
/ gawk
dapat melakukan hal-hal seperti itu pada prinsipnya, tetapi dapatkah mereka juga bekerja dengan file kamus seperti itu? Sepertinya gawk
akan menjadi kandidat yang tepat untuk magiccommand
, apa magicflags
yang benar? ? Bagaimana saya perlu memformat dictionary.txt
saya? ?
Jawaban yang Diterima:
Inilah salah satu cara dengan sed
:
sed '
s|"(.*)"[[:blank:]]*:[[:blank:]]*"(.*)"|1
2|
h
s|.*n||
s|[&/]|\&|g
x
s|n.*||
s|[[.*^$/]|\&|g
G
s|(.*)n(.*)|s/1/2/g|
' dictionary.txt | sed -f - novel.txt
Cara kerjanya:
sed
pertama ternyata dictionary.txt
ke dalam file skrip (perintah pengeditan, satu per baris). Ini disalurkan ke sed
ke-2 (perhatikan -f -
yang berarti membaca perintah dari stdin
) yang menjalankan perintah tersebut, mengedit novel.txt
.
Ini memerlukan terjemahan format Anda
"STRING" : "REPLACEMENT"
menjadi sed
perintah dan keluar dari karakter khusus apa pun dalam proses untuk LHS
dan RHS
:
s/ESCAPED_STRING/ESCAPED_REPLACEMENT/g
Jadi substitusi pertama
s|"(.*)"[[:blank:]]*:[[:blank:]]*"(.*)"|1
2|
ternyata "STRING" : "REPLACEMENT"
ke dalam STRINGnREPLACEMENT
(n
adalah karakter baris baru). Hasilnya kemudian disalin ke h
ruang lama.s|.*n||
menghapus bagian pertama hanya menyimpan REPLACEMENT
lalu s|[&/]|\&|g
lolos dari karakter yang dicadangkan (ini adalah RHS
).
Kemudian ex
mengubah buffer penahan dengan ruang pola dan s|n.*||
menghapus bagian kedua hanya menyimpan STRING
dan s|[[.*^$/]|\&|g
melakukan pelarian (ini adalah LHS
).
Konten buffer penahan kemudian ditambahkan ke ruang pola melalui G
jadi sekarang konten ruang pola adalah ESCAPED_STRINGnESCAPED_REPLACEMENT
.
Pergantian terakhir
s|(.*)n(.*)|s/1/2/g|
mengubahnya menjadi s/ESCAPED_STRING/ESCAPED_REPLACEMENT/g