Verwendung von 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
Verwendung:
awk -f script.awk file
Test:
# echo "the quick brown fox jumps over the lazy dog" | awk -f script.awk
the quick brown foch jumps over the lezy dog
Keine Antwort, nur um eine kürzere, idiomatische Art zu zeigen, den table[]
zu füllen Array aus der Antwort von @konsolebox, wie in den zugehörigen Kommentaren besprochen:
BEGIN {
split("a e b", old)
split("x ch o", new)
for (i in old)
table[old[i]] = new[i]
FS = OFS = ""
}
Die Zuordnung von alten zu neuen Zeichen wird also deutlich, indem das Zeichen im ersten split() den darunter liegenden Zeichen zugeordnet wird, und für jede andere gewünschte Zuordnung müssen Sie nur die Zeichenfolge(n) in ändern split(), nicht 26-ish explizite Zuweisungen an table[].
ändernSie können sogar ein allgemeines Skript erstellen, um Zuordnungen vorzunehmen, und einfach die alten und neuen Zeichenfolgen als Variablen übergeben:
BEGIN {
split(o, old)
split(n, new)
for (i in old)
table[old[i]] = new[i]
FS = OFS = ""
}
dann in der Shell so etwas:
old="a e b"
new="x ch o"
awk -v o="$old" -v b="$new" -f script.awk file
und Sie können sich vor Ihren eigenen Fehlern beim Füllen der Zeichenfolgen schützen, z. B.:
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]
}
}
Wäre es nicht gut zu wissen, ob Sie geschrieben haben, dass b auf x abbildet und später fälschlicherweise geschrieben haben, dass b auf y abbildet? Das Obige ist wirklich der beste Weg, dies zu tun, aber Sie müssen natürlich anrufen.
Hier ist eine vollständige Lösung, wie in den Kommentaren unten besprochen
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
}
Ich habe table
umbenannt Array als map
nur weil iMHO das den Zweck des Arrays besser darstellt.
Speichern Sie das obige in einer Datei script.awk
und führen Sie es als awk -f script.awk inputfile
aus
Dies kann ganz kurz mit einem Perl-Einzeiler geschehen:
perl -pe '%h=(a=>"xy",c=>"z"); s/(.)/defined $h{$1} ? $h{$1} : $1/eg'
oder gleichwertig (danke jaypal):
perl -pe '%h=(a=>"xy",c=>"z"); s|(.)|$h{$1}//=$1|eg'
%h
ist ein Hash, der die Zeichen (Schlüssel) und ihre Substitutionen (Werte) enthält. s
ist der Substitutionsbefehl (wie in sed). Die g
Modifikator bedeutet, dass die Substitution global ist und der e
bedeutet, dass das Ersatzteil als Ausdruck ausgewertet wird. Es erfasst jedes Zeichen einzeln und ersetzt sie durch den Wert im Hash, falls vorhanden, behält ansonsten den ursprünglichen Wert bei. Die -p
Schalter bedeutet, dass jede Zeile in der Eingabe automatisch gedruckt wird.
Testen Sie es aus:
$ perl -pe '%h=(a=>"xy",c=>"z"); s|(.)|$h{$1}//=$1|eg' <<<"abc"
xybz