Ich möchte eine Reihe von Zeichen durch entsprechende Zeichen aus einer anderen Reihe ersetzen, etwa so:
original set: ots
"target" set: u.x
foobartest → fuubar.ex.
Übersetzungen / Transliterationen wie diese sind die Spezialität des tr
Befehls:
$ echo 'foobartest' | tr 'ots' 'u.x'
fuubar.ex.
Leider wird tr
das Ändern von Dateien an Ort und Stelle nicht unterstützt, wie dies der sed
Fall ist.
Ich würde es gerne verwenden, sed
damit ich das Rad des Jonglierens von temporären Dateien nicht neu erfinden muss.
tr
(Richtig) Ignoriert die Rekursion in den Ersatzsätzen:echo 'abc' | tr ab bx
→bxc
. Bei einer primitiven Lösung wird dies möglicherweise abgeschlachtet,xxc
da die Übersetzung erneut auf bereits übersetzte Zeichen angewendet wird.sed
Gegensatz zu GNUtr
kann Multi-Byte-Zeichen transkribieren)Antworten:
sed
hat deny
Befehl, der wie folgt funktionierttr
:Der
y
Befehl ist Teil der POSIX-sed
Spezifikation und sollte daher auf nahezu jeder Plattform funktionieren.Und da dies der
sed
Fall ist, können Sie eine Datei durch die bearbeitete Version ersetzen , wodurch Sie das lästige Geschäft mit temporären Dateien vermeiden (vorausgesetzt, Ihre Implementierungsed
unterstützt die-i
Option, die von POSIX nicht angegeben wird):quelle
sed
, heißt das nicht, dass auch die anderen Funktionen so sind. ;) Die Vim-Mailingliste enthält einen Thread zum Auffinden einesy/abc/def/
Äquivalents. Die beste Option scheint zu sein:%call setline(".", tr(getline("."),"abc","def"))
.Wenn Sie wie in Ihrem Fall Zeichen transliterieren, ohne ihre Größe zu ändern (einige Implementierungen wie GNU unterstützen jedoch
tr
nur Einzelbyte-Zeichen), können Sie Folgendes tun:Das heißt, habe
tr
die Datei über sich selbst überschrieben.Das ist besser als
sed -i
aus mehreren Gründen:Ein Nachteil ist, dass die Datei bei einer Unterbrechung zur Hälfte übersetzt wird (in diesem Fall können Sie sie jedoch erneut ausführen, um sie zu beenden). Einige
sed
Implementierungen würden dies korrekt handhaben, indem sie sicherstellen, dass die ursprüngliche Datei unverändert bleibt, es sei denn, der Befehl ist erfolgreich.quelle
echo 'abc' | tr ab bx
.tr
und in unserer symlinklastigen PXE-Umgebung gabsed -i
es ein Problem zu passieren ...: /iconv -t cp437
scheint dafür besser geeignet zu sein.iconv
bricht ab, wenn die Eingabedatei bereits cp437-codierte Bytes oder eine Mischung aus mehreren Codierungen enthält. Während es im Allgemeinen vorzuziehen ist, ist es in diesem Fall robuster, manuelle Ersetzungen vorzunehmen.Wenn das Hauptproblem in der mangelnden Unterstützung für das Ändern von Dateien besteht, ist das
sponge
Tool aus dem moreutils-Paket möglicherweise für Sie von Interesse :schreibt in
file
, wird aber erstfile
zum Schreiben geöffnet , wenn die Eingabe abgeschlossen ist. Aus der Manpage :Es sei denn, Sie haben wirklich große Dateien, die nicht im Speicher gehalten werden können,
sponge
könnten für Sie arbeiten.quelle
sponge
ist, dass es immer noch überschreibt,file
wenntr
fehlschlägt (zum Beispiel, wenn Sie schreiben, aber keinen Lesezugriff hattenfile
)cat file >; file
Operator von ksh93, der die Ausgabe in ein tempfile schreibt, das nur dann in das Ziel umbenannt wird, wenn der Befehl erfolgreich ausgeführt wurde (aber sosed -i
wird eine neue Datei erstellt, anstatt das Original zu überschreiben).