2016-08-09 8 views
1

Ich habe eine Datei, in der die Spalten durch mehrere Leerzeichen getrennt sind.Wenn Spalten durch mehrere Leerzeichen getrennt sind, wie ändert man eine Spalte und behält die Leerzeichen?

Wie kann ich die zweite Spalte festlegen und die Leerzeichen in der Zeile beibehalten?

Zum Beispiel in Postgres' pg_hba.conf gibt es eine Zeile

local all all   peer 

Wie kann ich ändern ‚Peer‘ zu ‚Vertrauen‘ und halten die Räume, wie sie auf der Linie sind? Wenn ich awk tun $4="trust" gibt es ein Leerzeichen zwischen den Spalten. Im Prinzip ist das OK, aber es macht die Datei schwieriger zu lesen, wegen der Position der Header über der Zeile in der Datei.

+0

könnten Sie geben ein Beispiel zu klären, was Sie suchen? – fedorqui

+0

Verwenden Sie '-F '\ t'' für das Spaltentrennzeichen und setzen Sie die zweite Spalte mit' $ 2 = ... '. – oliv

+0

Es tut mir leid, ich sehe, dass die Spalten durch mehrere Leerzeichen getrennt sind. Aber vielleicht ist das egal. Die Datei ist postgres 'pg_hba.conf und eine Zeile sieht so aus: 'local all all peer', Wie kann ich' peer 'auf' trust 'setzen und die Leerzeichen so behalten wie sie sind? Die Anzahl der Leerzeichen zwischen den Spalten ist unterschiedlich, aber stackoverflow zeigt das nicht an. Wenn ich awk auf '$ 4 = trust 'lasse, werden alle Leerzeichen zwischen 2 Spalten in 1 Leerzeichen zusammengefasst. – ericj

Antwort

0

Sie können wirklich nicht. Wenn die Menge an Speicherplatz zwischen Feldern variiert. Wenn Sie einen Feldwert ändern, wird der Datensatz neu erstellt, dh das Feldtrennzeichen FS wird durch das Ausgabefeldtrennzeichen OFS ersetzt.

Sie können Ihr Glück mit Regex versuchen, obwohl.

1

hier ist ein Ansatz

$ echo "local all all   peer" | 
    awk 'gsub("peer","trust")' 

local all all   trust 

hier ist ein weiterer Ansatz, wenn Sie das Feld nicht von Wert sind zu ändern, sondern durch den Index. Zum Beispiel drittes Feld ändern, um „Vertrauen“ dieser Zeit

$ echo "local all all   peer" | 
    awk -v RS='[^ ]+' -v ORS="" '{print $0 (NR==3?"trust":RT)}' 

local all trust   peer 
+0

Tun Sie das nicht, es wird fehlschlagen, wenn "peer" als Teil einer früheren Spalte erscheint. Versuchen Sie, bei diesem Ansatz Feld 3 ('all') durch' trust' zu ersetzen. –

+0

Sie sollten erwähnen, die zweite Lösung ist gawk-spezifisch. Außerdem funktioniert es nur, wenn es nur eine Eingabezeile gibt. Es funktioniert nicht, wenn Tabulatoren zwischen Feldern vorhanden sind, und es wird kein Zeilenumbruch am Ende der Ausgabe gedruckt, wenn Sie das vierte Feld ersetzen. –

1

Sie benötigen einen regulären Ausdruck und arbeiten auf dem gesamten Datensatz zu verwenden, um wie viele Anfangsfelder (\S+) sowie Separatoren Angabe (\s+) zu überspringen, bevor Sie Ihre Änderungen vorzunehmen , z.B mit GNU awk für gensub() und \s/\S:

$ awk '{$0=gensub(/(\s*(\S+\s+){3})\S+/,"\\1trust",1)}1' file 
local all all   trust 

ändert Feld 3 ein härterer/besserer Test für jede mögliche Lösung ist, da es Inhalte (all) erscheinen früher in der Zeile zu:

$ awk '{$0=gensub(/(\s*(\S+\s+){2})\S+/,"\\1trust",1)}1' file 
local all trust   peer 

Die Regexp beginnt mit \s* seit awk ignoriert führenden Leerraum, aber das ist nicht wirklich für Ihre spezifischen Daten benötigt.

Mit anderen awks würden Sie tun:

$ awk 'match($0,/[[:space:]]*([^[:space:]]+[[:space:]]+){2}/) { 
    head = substr($0,1,RLENGTH) 
    tail = substr($0,RLENGTH+1) 
    sub(/[^[:space:]]+/,"trust",tail) 
    print head tail 
}' file 
local all trust   peer 
Verwandte Themen