Risposte:
L' -Fopzione ha bisogno di un argomento: -F,ad esempio.
La fine dello awkscript deve essere separata con un (space char) con il resto dei parametri.
Se il separatore di campo è ,e si desidera mantenerlo e se il numero di colonne è costante e inferiore o uguale a 11, provare a questo:
awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"
command file > newfile && mv newfile file. Detto questo, la versione più recente di GNU awkper sostenere questo: gawk -i inplace '{blah blah}' file.
mv newfile filete puoi usare cat newfile > file ; rm -f newfile- questo conserva l'inode e le autorizzazioni di file.
mktemppiuttosto che codificare i nomi dei file temporanei negli script. ad esempiotf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
La soluzione più breve sarebbe
awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file
Non sono sicuro ,+che funzionerà in tutte le awkversioni, ma funziona almeno in awk GNU, anche con la -cmodalità ompatibilità.
Spiegazione:
$(NF+1)=$7: prima aggiungiamo il 7 ° campo alla fine della riga (potrebbe essere $12=$7in questo caso)$7="": nel passaggio successivo il 7 ° campo viene cancellato (ma i delimitatori circostanti rimangono)$0=$0) trattando più virgole come separatore di campo (questo viene fatto tramite -F',+', qui +significa una o più volte), e anche riorganizzare il record corrente tramite $1=$1per forzare la ricostruzione della linea utilizzando il campo di output precedentemente impostato separatore (impostato da un'opzione -v OFS=,)1Esempio di input:
1,2,3,4,5,6,7,8,9,10,11
produzione
1,2,3,4,5,6,8,9,10,11,7
,+dovrebbe funzionare.
all,ball,call,,,fall→ all,ball,call,fall). (2) $(NF+1)=$7è un approccio intelligente. IMHO, $0 = $0 OFS $7è un po 'più chiaro, solo un paio di personaggi in più, e sembra fare la stessa cosa. Riesci a pensare a una situazione in cui $0 = $0 OFS $7non fa lo stesso del tuo codice?
$0=$0 OFS $7è probabilmente identico a $(NF+1)=$7, ma solo con il resto del codice invariato, non in generale.
Se stai stampando con OFS=, quindi senza un separatore tra i campi, puoi semplicemente salvare il valore di $7in una variabile, impostare $7su vuoto e stampare direttamente la linea e la variabile. Non è necessario specificare tutti i campi:
$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file
12345687
Probabilmente intendi:
awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"
awknon vede mai le virgolette singole OFS='', giusto? Puoi anche solo digitare OFS=; è esattamente lo stesso.
Lei non ha espressamente detto che volevi usare awk, e hai detto che volevi usare la modifica sul posto come fornito da sed -i, ecco un sed -ivariante. Di solito awkè meglio per lavorare con le colonne, ma questo è un caso in cui preferisco sed, perché gestisce naturalmente un numero arbitrario di colonne.
MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv
Spiegazione:
-r seleziona regexps estesi in modo da evitare molte barre rovesciateNaturalmente questo non funzionerà con i file che nascondono le virgole tra virgolette (o peggio, sfuggirle), ma awk non lo gestirà senza alcune acrobazie serie. Se hai questo problema, staresti meglio con il perlmodulo Text:CSVo il pythonmodulo csv.
Un paio di awkvarianti (supponendo che il tuo file sia all'interno della variabile $file)
Qui è possibile scorrere per tutta la colonna, stampare con il separatore di campo (OFS) e stampare il terminatore di registrazione (ORS) alla fine della riga.
awk -F',' -v OFS=, \
'{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
printf "%s",$7;printf ORS}' "$file"Qui con l'utilizzo di una regex e la gensub()funzione
gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"
uccidendo il 7 ° campo e stampandolo alla fine della riga.
$0 è l'intero record $nè l' ennesimo record NF è il numero di campi della riga corrente OFS il separatore archiviato in uscitaORS il terminatore del record di output1è il trucco per dire di awk truee stampare il valore predefinito ( $0).Aggiorna ...
Quasi dimentico, è possibile spostare tutte le colonne seguendo la settima .
awk -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"
OFS $7sarebbe più robusto di "," $7. (2) Credo che ", " $7sia sbagliato, in quanto la domanda indica che l'OP non vuole spazi dopo le virgole. (E, se i dati di input avessero spazi dopo le virgole, allora $7inizierebbero già con uno spazio e ne aggiungeresti uno in più.)
OFS $7, non solo più robusto, ma anche più generale ( "la fretta fa sprecare" )
^indica la parte specifica del comando in cui è stato rilevato l'errore.