Odpowiedzi:
-F
Opcja wymaga argumentu: -F,
na przykład.
Koniec awk
skryptu musi być oddzielony znakiem (spacją) z resztą parametrów.
Jeśli separatorem pól jest ,
i chcesz go zachować, a liczba kolumn jest stała i mniejsza lub równa 11, spróbuj tego:
awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"
command file > newfile && mv newfile file
. Powiedział, że nowsza wersja GNU awk
wspierać w ten sposób: gawk -i inplace '{blah blah}' file
.
mv newfile file
ciebie możesz użyć cat newfile > file ; rm -f newfile
- to zachowuje i-węzeł i uprawnienia file
.
mktemp
zamiast skryptów tymczasowych nazw plików w skryptach. np.tf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
Byłoby krótsze rozwiązanie
awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file
Nie jestem pewien, czy ,+
będzie działał we wszystkich awk
wersjach, ale działa przynajmniej w GNU awk, także w -c
trybie zgodności.
Wyjaśnienie:
$(NF+1)=$7
: najpierw dodajemy siódme pole na końcu linii (może być $12=$7
w tym przypadku)$7=""
: w następnym kroku 7. pole jest usuwane (ale otaczające ograniczniki pozostają)$0=$0
) traktując wiele przecinków jako separator pól (odbywa się to przez -F',+'
, tutaj +
oznacza jeden lub więcej razy), a także zmienić kolejność bieżącego rekordu, $1=$1
aby wymusić przebudowę linii za pomocą wcześniej ustawionego pola wyjściowego separator (ustawiany przez opcję -v OFS=,
)1
Przykładowe dane wejściowe:
1,2,3,4,5,6,7,8,9,10,11
wynik
1,2,3,4,5,6,8,9,10,11,7
,+
powinno działać.
all,ball,call,,,fall
→ all,ball,call,fall
). (2) $(NF+1)=$7
to sprytne podejście. IMHO $0 = $0 OFS $7
jest nieco jaśniejszy, ma tylko kilka znaków dłużej i wydaje się, że robi to samo. Czy możesz pomyśleć o sytuacji, w której $0 = $0 OFS $7
kod nie działa tak samo jak kod?
$0=$0 OFS $7
jest prawdopodobnie identyczny $(NF+1)=$7
, ale tylko z resztą kodu niezmienioną, ogólnie nie.
Jeśli drukujesz za pomocą OFS=
, więc bez separatora między polami, możesz po prostu zapisać wartość $7
zmiennej, ustawić $7
puste i wydrukować linię i zmienną bezpośrednio. Nie musisz określać wszystkich pól:
$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file
12345687
Prawdopodobnie masz na myśli:
awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"
awk
nigdy nie widzi pojedynczych cytatów OFS=''
, prawda? Równie dobrze możesz po prostu pisać OFS=
; jest dokładnie tak samo.
Nie specjalnie powiedzieć, że chciał użyć awk, a nie mówią, że chciał użyć edycji w miejscu jak zapewnia sed -i
, więc o to sed -i
wariant. Zwykle awk
lepiej jest pracować z kolumnami, ale jest to jeden przypadek, w którym wolę sed
, ponieważ naturalnie obsługuje dowolną liczbę kolumn.
MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv
Wyjaśnienie:
-r
wybiera rozszerzone wyrażenia regularne, aby uniknąć mnożenia odwrotnych ukośnikówOczywiście nie będzie to działać z plikami, które ukrywają przecinki w cudzysłowach (lub, co gorsza, unikaj ich), ale awk nie poradzi sobie z tym bez poważnych działań akrobatycznych. Jeśli masz ten problem, lepiej skorzystaj z perl
modułu Text:CSV
lub python
modułu csv
.
Kilka awk
wariantów (zakładając, że plik znajduje się w zmiennej $file
)
Tutaj możesz przejechać cały kolor, wydrukować za pomocą separatora pól (OFS) i wydrukować terminator rekordów (ORS) na końcu wiersza.
awk -F',' -v OFS=, \
'{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
printf "%s",$7;printf ORS}' "$file"
Tutaj z użyciem wyrażenia regularnego i gensub()
funkcji
gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"
zabijanie na 7 th pola i drukowanie go na końcu linii.
$0
to cały rekord $n
jest n- tym rekordem NF
to liczba pól bieżącej linii OFS
separator wyjściowy złożonyORS
terminator rekordu wyjściowego1
to sztuczka, by powiedzieć awk true
i wydrukować default ( $0
).Zaktualizuj ...
Prawie zapominam, że możliwe jest przesunięcie wszystkich kolumn po siódmej .
awk -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"
OFS $7
byłby bardziej solidny niż "," $7
. (2) Uważam, że ", " $7
jest to złe, o ile pytanie wskazuje, że OP nie chce spacji po przecinkach. (A jeśli dane wejściowe miałyby spacje po przecinkach, wtedy $7
już zaczynałyby się spacją, a ty dodawalibyśmy dodatkową.)
OFS $7
, że nie tylko bardziej solidny, ale nawet bardziej ogólny ( „pośpiech czyni marnotrawstwo” )
^
Wskazuje część konkretnego polecenia gdzie napotkał błąd.