Reorganizando colunas usando o awk

10

Estou tentando mover a 7ª coluna do meu arquivo csv para o final usando

awk -F '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}',OFS= "$file"

em que $ file é um arquivo .csv em um diretório. No entanto, a saída é

awk:                          ^ syntax error

Alguém sabe como corrigir esse erro?

    
por rmb 05.07.2016 / 14:49

6 respostas

8

A opção -F precisa de um argumento: -F, , por exemplo.

O final do script awk deve ser separado por um (caractere de espaço) com o restante dos parâmetros.

Se o separador de campo for , e você desejar mantê-lo, e se o número da coluna for constante e menor ou igual a 11, tente:

awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"
    
por 05.07.2016 / 15:00
7

Uma solução mais curta seria

awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file

Não tenho certeza se ,+ funcionará em todas as awk versões, mas funcionará pelo menos no GNU awk, também com -c ompatibility mode.

Explicação:

  • $(NF+1)=$7 : primeiro adicionamos o 7º campo ao final da linha (pode ser $12=$7 neste caso)
  • $7="" : na próxima etapa, o 7º campo é apagado (mas os delimitadores adjacentes permanecem)
  • para remover os delimitadores, precisamos repor o registro inteiro (via $0=$0 ) tratando várias vírgulas como separador de campo (isso é feito via -F',+' , aqui + significa uma ou mais vezes) e também reorganizar a corrente gravar via $1=$1 para forçar a recriação da linha usando o separador de campos de saída definido anteriormente (definido por uma opção -v OFS=, )
  • depois de concluir o embaralhamento, estamos prontos para imprimir o resultado com 1

Exemplo de entrada:

1,2,3,4,5,6,7,8,9,10,11

saída

1,2,3,4,5,6,8,9,10,11,7
    
por 05.07.2016 / 15:37
4

Se você estiver imprimindo com OFS= , portanto, sem um separador entre os campos, você pode simplesmente salvar o valor de $7 em uma variável, definir $7 para esvaziar e imprimir a linha e a variável diretamente. Você não precisa especificar todos os campos:

$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file 
12345687
    
por 05.07.2016 / 15:34
3

Você provavelmente quer dizer:

awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"
    
por 05.07.2016 / 14:55
3

Você não disse especificamente que queria usar o awk, e fez dizer que queria usar a edição no local, como fornecido por sed -i , portanto, aqui está uma sed -i variant. Geralmente, awk é melhor para trabalhar com colunas, mas esse é um caso em que prefiro sed , porque ele naturalmente lida com números arbitrários de colunas.

MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/,/" -i test.csv

Explicação:

  • -r seleciona regexps estendidos, por isso, evitamos muitas barras invertidas
  • o primeiro grupo é $ N repetições de sequências terminadas por vírgula, em outras palavras, as colunas antes da que queremos mover, com uma vírgula final
  • segundo grupo é a repetição $ N-th, nos esquecemos disso
  • terceiro grupo é a coluna que queremos mover, sem a vírgula final
  • O
  • quarto grupo é composto por todas as colunas depois daquelas que queremos mover, sem vírgula antes
  • substituímos pelo primeiro grupo, pelo último grupo e pela coluna extraída, inserindo a vírgula conforme necessário.

É claro que isso não funcionará com arquivos que escondem vírgulas entre aspas (ou pior, escape delas), mas o awk não vai lidar com isso sem acrobacias sérias. Se você tiver esse problema, será melhor usar perl module Text:CSV ou python module csv .

    
por 06.07.2016 / 00:06
2

Um par de awk variants (supondo que seu arquivo esteja dentro da variável $file )

  • Aqui você pode alternar entre todas as cores, imprimir com o separador de campo (OFS) e imprimir o terminador de registro (ORS) no final da linha.

    awk  -F',' -v OFS=,                                \
    '{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
    printf "%s",$7;printf ORS}' "$file"
    
  • Aqui, usando um regex e a função gensub()

    gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"
    

    matando o campo th e imprimindo no final da linha.

    • $0 é o registro inteiro
    • $n é o registro th
    • NF é o número de campos da linha atual
    • OFS o separador arquivado de saída
    • ORS o terminador de registro de saída
    • 1 é o truque para dizer ao awk true e imprimir o padrão ( $0 ).

Atualizar ...

Quase me esqueço, é possível deslocar todas as colunas após o 7 th .

awk  -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"
    
por 05.07.2016 / 16:20