Menggunakan Awk:
#!/usr/bin/awk -f
BEGIN {
FS = OFS = ""
table["a"] = "e"
table["x"] = "ch"
# and so on...
}
{
for (i = 1; i <= NF; ++i) {
if ($i in table) {
$i = table[$i]
}
}
}
1
Penggunaan:
awk -f script.awk file
Tes:
# echo "the quick brown fox jumps over the lazy dog" | awk -f script.awk
the quick brown foch jumps over the lezy dog
Bukan jawaban, hanya untuk menunjukkan cara yang lebih singkat dan idiomatis untuk mengisi table[]
array dari jawaban @konsolebox seperti yang dibahas dalam komentar terkait:
BEGIN {
split("a e b", old)
split("x ch o", new)
for (i in old)
table[old[i]] = new[i]
FS = OFS = ""
}
jadi pemetaan karakter lama ke baru ditampilkan dengan jelas bahwa karakter di split() pertama dipetakan ke karakter di bawahnya dan untuk pemetaan lain yang Anda inginkan, Anda hanya perlu mengubah string di split(), bukan mengubah penetapan eksplisit 26-ish ke table[].
Anda bahkan dapat membuat skrip umum untuk melakukan pemetaan dan hanya meneruskan string lama dan baru sebagai variabel:
BEGIN {
split(o, old)
split(n, new)
for (i in old)
table[old[i]] = new[i]
FS = OFS = ""
}
lalu di shell seperti ini:
old="a e b"
new="x ch o"
awk -v o="$old" -v b="$new" -f script.awk file
dan Anda dapat melindungi diri dari kesalahan Anda sendiri dalam mengisi string, misalnya:
BEGIN {
numOld = split(o, old)
numNew = split(n, new)
if (numOld != numNew) {
printf "ERROR: #old vals (%d) != #new vals (%d)\n", numOld, numNew | "cat>&1"
exit 1
}
for (i=1; i <= numOld; i++) {
if (old[i] in table) {
printf "ERROR: \"%s\" duplicated at position %d in old string\n", old[i], i | "cat>&2"
exit 1
}
if (newvals[new[i]]++) {
printf "WARNING: \"%s\" duplicated at position %d in new string\n", new[i], i | "cat>&2"
}
table[old[i]] = new[i]
}
}
Bukankah lebih baik untuk mengetahui jika Anda menulis bahwa b memetakan ke x dan kemudian secara keliru menulis bahwa b memetakan ke y? Di atas benar-benar adalah cara terbaik untuk melakukan ini tetapi panggilan Anda tentu saja.
Inilah satu solusi lengkap seperti yang dibahas dalam komentar di bawah
BEGIN {
numOld = split("a e b", old)
numNew = split("x ch o", new)
if (numOld != numNew) {
printf "ERROR: #old vals (%d) != #new vals (%d)\n", numOld, numNew | "cat>&1"
exit 1
}
for (i=1; i <= numOld; i++) {
if (old[i] in table) {
printf "ERROR: \"%s\" duplicated at position %d in old string\n", old[i], i | "cat>&2"
exit 1
}
if (newvals[new[i]]++) {
printf "WARNING: \"%s\" duplicated at position %d in new string\n", new[i], i | "cat>&2"
}
map[old[i]] = new[i]
}
FS = OFS = ""
}
{
for (i = 1; i <= NF; ++i) {
if ($i in map) {
$i = map[$i]
}
}
print
}
Saya mengganti nama table
array sebagai map
hanya karena iMHO yang lebih mewakili tujuan dari array.
simpan di atas dalam file script.awk
dan jalankan sebagai awk -f script.awk inputfile
Ini dapat dilakukan dengan cukup ringkas menggunakan Perl one-liner:
perl -pe '%h=(a=>"xy",c=>"z"); s/(.)/defined $h{$1} ? $h{$1} : $1/eg'
atau yang setara (terima kasih jaypal):
perl -pe '%h=(a=>"xy",c=>"z"); s|(.)|$h{$1}//=$1|eg'
%h
adalah hash yang berisi karakter (kunci) dan penggantinya (nilai). s
adalah perintah substitusi (seperti pada sed). g
pengubah berarti substitusi bersifat global dan e
berarti bahwa bagian pengganti dievaluasi sebagai ekspresi. Itu menangkap setiap karakter satu per satu dan menggantinya dengan nilai di hash jika ada, jika tidak, simpan nilai aslinya. -p
switch berarti bahwa setiap baris dalam input dicetak secara otomatis.
Mengujinya:
$ perl -pe '%h=(a=>"xy",c=>"z"); s|(.)|$h{$1}//=$1|eg' <<<"abc"
xybz