Antworten:
Die -F
Option benötigt ein Argument: -F,
zum Beispiel.
Das Ende des awk
Skripts muss durch ein (Leerzeichen) mit den restlichen Parametern getrennt werden.
Wenn das Feldtrennzeichen ist ,
und Sie es behalten möchten und wenn die Anzahl der Spalten konstant und kleiner oder gleich 11 ist, versuchen Sie Folgendes:
awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"
command file > newfile && mv newfile file
. Das sei gesagt, neuere Version von GNU awk
dies zu unterstützen: gawk -i inplace '{blah blah}' file
.
mv newfile file
verwenden cat newfile > file ; rm -f newfile
- dies bewahrt den Inode und die Berechtigungen von file
.
mktemp
temporäre Dateinamen in Skripten zu verwenden, anstatt sie hart zu codieren. zBtf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
Kürzere Lösung wäre
awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file
Ich bin mir nicht sicher, ob ,+
es in allen awk
Versionen funktionieren wird, aber es funktioniert zumindest in GNU awk, auch im -c
Kompatibilitätsmodus.
Erläuterung:
$(NF+1)=$7
: Zuerst fügen wir das 7. Feld am Ende der Zeile hinzu (könnte $12=$7
in diesem Fall sein)$7=""
: im nächsten Schritt wird das 7. Feld gelöscht (die umgebenden Begrenzer bleiben jedoch erhalten)$0=$0
) mehrere Kommas getrennt behandeln (dies über getan wird -F',+'
, hier +
bedeutet ein oder mehrere Male) und auch aktuelle Datensatz über neu ordnen , $1=$1
um Kraft den Wiederaufbau der Linie mit zuvor eingestellten Ausgabefeld Trennzeichen (durch eine Option gesetzt -v OFS=,
)1
Beispiel Eingabe:
1,2,3,4,5,6,7,8,9,10,11
Ausgabe
1,2,3,4,5,6,8,9,10,11,7
,+
sollte also funktionieren.
all,ball,call,,,fall
→ all,ball,call,fall
). (2) $(NF+1)=$7
ist ein kluger Ansatz. IMHO $0 = $0 OFS $7
ist ein bisschen klarer, nur ein paar Zeichen länger und es scheint dasselbe zu tun. Können Sie sich eine Situation vorstellen, in der $0 = $0 OFS $7
nicht das Gleiche wie in Ihrem Code geschieht?
$0=$0 OFS $7
ist wahrscheinlich identisch mit $(NF+1)=$7
, aber nur mit dem Rest des Codes unverändert, nicht im Allgemeinen.
Wenn Sie mit drucken OFS=
, also ohne Trennzeichen zwischen den Feldern, können Sie einfach den Wert von $7
in einer Variablen speichern , $7
auf leer setzen und die Zeile und die Variable direkt drucken. Sie müssen nicht alle Felder angeben:
$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file
12345687
Sie meinen wahrscheinlich:
awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"
awk
nie die einfachen Anführungszeichen in sieht OFS=''
, nicht wahr? Sie können genauso gut einfach tippen OFS=
; es ist genau das gleiche.
Sie haben nicht ausdrücklich angegeben, dass Sie awk verwenden möchten, und Sie haben angegeben, dass Sie die von bereitgestellte In-Place-Bearbeitung verwenden möchten. Daher sed -i
hier eine sed -i
Variante. Normalerweise awk
ist es besser, mit Spalten zu arbeiten, aber in diesem Fall bevorzuge ich sed
, weil es natürlich eine beliebige Anzahl von Spalten verarbeitet.
MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv
Erläuterung:
-r
wählt erweiterte reguläre Ausdrücke aus, um viele umgekehrte Schrägstriche zu vermeidenNatürlich funktioniert dies nicht mit Dateien, die Kommas in Anführungszeichen verbergen (oder, schlimmer noch, sie maskieren), aber awk wird das auch nicht ohne ernsthafte Akrobatik schaffen. Wenn Sie dieses Problem haben, sind Sie mit dem perl
Modul Text:CSV
oder dem python
Modul besser dran csv
.
Einige awk
Varianten (vorausgesetzt, Ihre Datei befindet sich in der Variablen $file
)
Hier können Sie die gesamte Spalte durchlaufen, mit dem Feldtrennzeichen (OFS) drucken und das Satzendezeichen (ORS) am Ende der Zeile drucken.
awk -F',' -v OFS=, \
'{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
printf "%s",$7;printf ORS}' "$file"
Hier mit einem regulären Ausdruck und der gensub()
Funktion
gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"
Tötung der 7 - ten Feld und es am Ende der Zeile zu drucken.
$0
ist der ganze Rekord $n
ist der n- te Rekord NF
ist die Anzahl der Felder der aktuellen Zeile OFS
das Ausgabefeld TrennzeichenORS
das Ausgabesatz-Abschlusszeichen1
ist der Trick, um awk zu sagen true
und den default ( $0
) zu drucken .Aktualisieren ...
Ich habe fast vergessen, dass es möglich ist, alle Spalten nach der siebten zu verschieben.
awk -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"
OFS $7
wohl robuster als "," $7
. (2) Ich halte das ", " $7
für falsch, sofern aus der Frage hervorgeht, dass das OP keine Leerzeichen nach den Kommas will. (Und wenn die Eingabedaten Leerzeichen nach den Kommas enthielten, $7
würde dies bereits mit einem Leerzeichen beginnen, und Sie würden ein zusätzliches hinzufügen.)
OFS $7
, nicht nur robuster, sondern auch allgemeiner ( "Eile macht Verschwendung" )
^
gibt den spezifischen Teil des Befehls an, an dem der Fehler aufgetreten ist.