Ich habe eine Datei mit einer Reihe von Hostnamen, die mit IPs korreliert sind und folgendermaßen aussehen:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int.test.example.com 59.2.86.3
super.awesome.machine 123.234.15.6
Ich möchte, dass es so aussieht:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int-test-example-com 59.2.86.3
super-awesome-machine 123.234.15.6
Wie kann ich das ersetzen? (Punkte) aus der ersten Spalte mit - (Bindestrich), um eine Sortierung nach der zweiten Spalte zu erleichtern? Ich dachte daran, sed zu verwenden, um Punkte bis zum ersten Leerzeichen zu ersetzen, oder jeden Punkt außer den letzten drei zu ersetzen, aber ich habe Probleme, Regex und sed zu verstehen. Ich kann einfache Ersetzungen durchführen, aber das geht mir weit über den Kopf!
Dies ist Teil eines größeren Skripts, das ich in Bash geschrieben habe. Ich stecke in diesem Teil fest.
awk
basiert aufnawk
, daher sollten alle modernenawk
Implementierungen habengsub
. Unter Solaris benötigen Sie möglicherweise/usr/xpg4/bin/awk
odernawk
.Wenn Sie die Ersetzungen für das erste Feld vornehmen müssen, verwenden Sie am besten Rahuls awk-Lösung. Beachten Sie jedoch, dass dies den Abstand beeinträchtigen kann (Felder werden mit einem einzelnen Leerzeichen dazwischen neu geschrieben).
Sie können es vermeiden, indem Sie es stattdessen schreiben:
Das
-p
Flag bedeutet "Zeile für Zeile die Eingabedatei lesen und jede Zeile nach dem Anwenden des von angegebenen Skriptes drucken-e
". Ersetzen Sie dann (s|pattern|replacement|
) die erste Folge von Nicht-Leerzeichen (\S+
) durch das übereinstimmende Muster ($&
), nachdem Sie alle.
durch ersetzt haben-
. Der Trick besteht darin, zu verwenden,s|||e
wo dere
Operator einen Ausdruck als Ersatz auswertet. Sie können also einen Ersatz (tr/./-/
) auf das match ($&
) des vorherigen ( ) anwenden lassens|||e
.Wenn Sie jeden
.
durch einen-
außer den letzten 3 letzten ersetzen müssen , mit GNUsed
und unter der Annahme, dass Sie einenrev
Befehl haben:quelle
/r
damit dies funktioniert).Sed ist nicht das einfachste Werkzeug für den Job - siehe andere Antworten für bessere Werkzeuge - aber es kann getan werden.
Verwenden Sie in einer Schleife ,
.
um-
nur bis zum ersten Leerzeichen zu ersetzens
.(Beachten Sie, dass einige sed-Implementierungen keine Kommentare in derselben Zeile unterstützen. GNU sed tut dies.)
So führen Sie den Austausch stattdessen bis zum letzten Leerzeichen durch:
Eine andere Technik nutzt den Laderaum von sed. Speichern Sie das Bit, das Sie nicht ändern möchten, im Haltebereich, erledigen Sie Ihre Arbeit und rufen Sie den Haltebereich ab. Hier teile ich die Linie am letzten Leerzeichen und ersetze Punkte im ersten Teil durch Bindestriche.
quelle
Da Rahul Ihnen die kanonische Antwort für Ihren Anwendungsfall gegeben hat, dachte ich, ich würde versuchen, das Titelproblem zu beantworten: Ersetzen Sie alle bis auf die letzten x Vorkommen eines regulären Ausdrucks:
Der obige Code (getestet) setzt nicht voraus, dass Sie durch Leerzeichen getrennte Felder haben. Es werden alle Punkte in einer Linie durch Bindestriche mit Ausnahme der letzten 3 Punkte ersetzt. Ersetzen Sie das
3
im Code nach Ihren Wünschen.quelle
Sie können hierfür viele verschiedene Tools verwenden. Rahul Patil hat dir bereits
gawk
eine gegeben, also hier ein paar andere:Perl
Der
-a
Schalter bewirkt, dass Perl die Eingabezeilen im Leerzeichen automatisch aufteilt und die resultierenden Felder im Array speichert@F
. Das erste Feld, deshalb wird sein ,$F[0]
so dass wir (ersetzens///
) alle Vorkommen.
mit-
im ersten Feld und dann das gesamte Array drucken.Schale
Hier liest die while-Schleife die Datei und teilt sie automatisch in Leerzeichen auf. Dadurch werden zwei Felder erstellt,
$first
und$rest
. Das Konstrukt${first//pattern/replacement}
ersetzt alle Vorkommen vonpattern
mitreplacement
.quelle
perlrun(1)
ich Ihnen sagen werde, dass dies der-a
"Autosplit-Modus" ist, stelle ich ihn mir lieber als "awk
Modus" vor: DIch glaube, das ist ein bisschen einfacher zu lesen als ein großer böser Regex. Grundsätzlich habe ich die Zeile im Leerzeichen einfach in zwei Felder aufgeteilt und im ersten Teil sed verwendet.
Abhängig von Ihrer Shell können Sie anstelle des Befehls sed auch $ {host //./-} verwenden.
quelle
Ohne
g
am Ende des Befehls zu verwenden, können Sie dies tun ... Dies ersetzt einfach das erste Vorkommen des Mustersquelle