Como trocar colunas em tal arquivo?

6

Eu tenho um arquivo de texto, cada linha é armazenada assim:

"Video or movie"    "parent"    "Media or entertainment"    "1" "1" "1" "0" "0"

Eu quero trocar as colunas 3 por 2, ou seja,

"Video or movie"   "Media or entertainment"  "parent"   "1" "1" "1" "0" "0"

Como fazer isso no linux em um script de shell ou qualquer outra linguagem de script? Eu só preciso de uma maneira mais simples e rápida de fazer isso.

    
por user11498 13.02.2012 / 21:32

7 respostas

10

Isso pode ser feito com awk usando " como o separador de campo. Mas, fazendo isso, você deve lembrar que $1 está vazio, $2 contém a primeira cadeia, $3 é o espaço entre cadeias, $4 é a segunda cadeia, etc. Além disso, é mais confiável trocar os dois seqüências de caracteres em vez de apenas imprimir todos os campos e esperando que você coloque bastante $n s. Tendo isso em mente, o seguinte deve funcionar:

awk 'BEGIN{OFS=FS="\""} {tmp=$4;$4=$6;$6=tmp;print}' input_file >output_file
    
por 13.02.2012 / 23:04
1

Aqui vai um sed rápido e sujo que faz isso:

sed -e 's/^\("[^"]*"\) *\("[^"]*"\) *\("[^"]*"\)/  /'

Mas falhará nos campos com aspas duplas em seus valores, etc.

Um exemplo:

echo \"a\" \"b\" \"c d d d\" \"e\" | sed -e 's/^\("[^"]*"\) *\("[^"]*"\)  *\("[^"]*"\)/  /'

Mas tenho certeza que alguém poderá mostrar a você um awk one-liner que é mais simples e melhor.

    
por 13.02.2012 / 21:37
1

Eu iria com:

sed 's/"\(.*\)"//' |
    awk 'BEGIN{FS="\" +\"";OFS="\" \""}{t=$3;$3=$2;$2=t;print}' |
    sed 's/.*/"&"/'

Os dois scripts sed manipulam as aspas duplas inicial e final (já que não são delimitadores e interferem). A cláusula BEGIN manipula a separação de campos. O t=$3;$3=$2;$2=t é um idioma de campos de troca padrão, então todo o campo é impresso (com OFS como o separador de campo).

    
por 13.02.2012 / 22:41
1

Este método é efetivamente idêntico ao método de Kevin awk . Eu o incluí aqui apenas como uma comparação entre bash e awk .

IFS=\";   # IFS sets up the split-at array delimiter
cat file |
while IFS= read -r line ;do              # Disable IFS for each 'read' 
    A=($line)                            # split into array elements
    t="${A[5]}";A[5]="${A[3]}";A[3]="$t" # swap "columns" 2 and 3
    for ((i=1;i<$((${#A[@]}));i++)) ;do
       printf '"%s' "${A[$i]}"           # print each element with a lead "
    done; echo '"'                       # add the final "
done
    
por 14.02.2012 / 01:29
0

E algo assim:

awk '{print $1, $3, $2, $4, $5, $6, $7, $8}' file > newfile
    
por 13.02.2012 / 22:23
0

Eu tenho duas soluções.

RESPOSTA ONE: Use sed 3 vezes para fazer o seguinte:

  1. inicie com a linha original: 12345678
  2. duplique os dois primeiros parâmetros: 1212345678
  3. corte o quarto parâmetro: 121345678
  4. corte o primeiro parâmetro: 21345678

Aqui está o comando resultante usando sed (usando XXX e YYY como ajudantes para localizar e remover os parâmetros 1 e 4):

sed 's/["][^"]*["][^"]*["][^"]*["]/XXX& & YYY/' data.txt | sed 's/["][^"]*["] YYY//' | sed 's/XXX["][^"]*["]//'

RESPOSTA DOIS: Converter dados em um script e executá-lo!

  • converta o data.txt em um data.sh inserindo um comando (digamos, flipcol.sh)
  • execute o data.sh

Implemente o flipcol.sh como:

echo '"'$2'"' '"'$1'"' '"'$3'"' '"'$4'"' '"'$5'"' '"'$6'"' '"'$7'"' '"'$8'"'

Em seguida, execute o seguinte comando em seu data.txt, criando um script de shell:

sed 's!^!./flipcol.sh !' < data.txt > data.sh

Em seguida, execute o script de shell recém-criado

./data.sh
    
por 14.02.2012 / 03:54
0

Suposições sobre as linhas no arquivo: elas começam com aspas duplas e o campo e os delimitadores não contêm aspas duplas. Então esta expressão sed funcionará:

sed 's@^\("[^"]*"[^"]*"\)\([^"]*\)\("[^"]*"\)\([^"]*\)@@'

Se esta expressão for seguida pelo nome do arquivo de texto, ele fornecerá a saída desejada, que pode ser colocada em um novo arquivo, seguindo o nome do arquivo de texto pelo redirecionador de saída > e o nome do novo arquivo desejado como:

sed 's@^\("[^"]*"[^"]*"\)\([^"]*\)\("[^"]*"\)\([^"]*\)@@' textfile > newfile
    
por 08.05.2018 / 15:13