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
使い方:
awk -f script.awk file
テスト:
# echo "the quick brown fox jumps over the lazy dog" | awk -f script.awk
the quick brown foch jumps over the lezy dog
table[]
に入力するためのより簡潔で慣用的な方法を示すためだけに、答えではありません 関連するコメントで説明されている @konsolebox の回答からの配列:
BEGIN {
split("a e b", old)
split("x ch o", new)
for (i in old)
table[old[i]] = new[i]
FS = OFS = ""
}
したがって、古い文字から新しい文字へのマッピングは、最初の split() の文字がその下の文字にマッピングされ、他のマッピングが必要な場合は、 split()、table[] への 26 っぽい明示的な代入を変更しないでください。
マッピングを行う一般的なスクリプトを作成して、古い文字列と新しい文字列を変数として渡すこともできます:
BEGIN {
split(o, old)
split(n, new)
for (i in old)
table[old[i]] = new[i]
FS = OFS = ""
}
シェルでは次のようになります:
old="a e b"
new="x ch o"
awk -v o="$old" -v b="$new" -f script.awk file
また、文字列を設定する際の間違いから身を守ることができます。例:
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]
}
}
b が x に写像すると書いた後で、誤って b が y に写像すると書いた場合、それを知っておくとよいでしょうか?上記は実際にこれを行うための最良の方法ですが、もちろんあなたの呼び出しです。
以下のコメントで説明されている 1 つの完全なソリューションを次に示します。
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
}
table
の名前を変更しました map
の配列 配列の目的をより適切に表す iMHO という理由だけで。
上記をファイル script.awk
に保存します awk -f script.awk inputfile
として実行します
これは、Perl ワンライナーを使用して非常に簡潔に行うことができます:
perl -pe '%h=(a=>"xy",c=>"z"); s/(.)/defined $h{$1} ? $h{$1} : $1/eg'
または同等のもの (jaypal に感謝):
perl -pe '%h=(a=>"xy",c=>"z"); s|(.)|$h{$1}//=$1|eg'
%h
文字 (キー) とその置換 (値) を含むハッシュです。 s
は置換コマンドです (sed と同様)。 g
修飾子は置換がグローバルであることを意味し、e
置換部分が式として評価されることを意味します。各文字を 1 つずつキャプチャし、存在する場合はハッシュの値で置き換え、存在しない場合は元の値を保持します。 -p
switch は、入力の各行が自動的に出力されることを意味します。
テスト:
$ perl -pe '%h=(a=>"xy",c=>"z"); s|(.)|$h{$1}//=$1|eg' <<<"abc"
xybz