AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / ubuntu / Perguntas / 1109777
Accepted
user2413
user2413
Asked: 2019-01-15 16:35:40 +0800 CST2019-01-15 16:35:40 +0800 CST 2019-01-15 16:35:40 +0800 CST

Mova a coluna específica do arquivo csv na frente (selecione a coluna pelo nome)

  • 772

Considere estes dados:

#!/usr/bin/env bash
cat > example_file.txt <<EOL
group, value, price
1, 3.21, 3.21
1, 3.42, 4.11
1, 3.5, 1.22
2, 4.1, 9.2
2, 4.2, 2.11
EOL

Eu quero mover a coluna 'valor' na frente:

value, price, group
3.21, 3.21, 1
3.42, 4.11, 1
3.5, 1.22, 1
4.1, 9.2, 2
4.2, 2.11, 2

o problema é: a ordem da coluna (ou mesmo o número da coluna ou o nome de muitas dessas colunas - exceto 'valor' que está sempre lá) varia de arquivo para arquivo. Portanto, tenho que selecionar a coluna de valor por nome (não por ordem).

Como posso fazer isso?

command-line bash text-processing csv
  • 4 4 respostas
  • 2625 Views

4 respostas

  • Voted
  1. aborruso
    2019-01-21T13:02:54+08:002019-01-21T13:02:54+08:00

    Com o grande Miller ( http://johnkerl.org/miller/doc ) é muito fácil

    mlr --csv reorder -f " value, price,group" input.csv
    

    Você tem

     value, price,group
     3.21, 3.21,1
     3.42, 4.11,1
     3.5, 1.22,1
     4.1, 9.2,2
     4.2, 2.11,2
    

    Observação: editei meu comando, levando em consideração os espaços nos campos nome da pergunta CSV

    • 9
  2. Best Answer
    steeldriver
    2019-01-15T18:03:51+08:002019-01-15T18:03:51+08:00

    Se você não se importa que a valuecoluna seja duplicada, você pode fazer algo assim, com csvtool:

    $ csvtool paste <(csvtool namedcol value example_file.txt) example_file.txt 
    value,group,value,price
    3.21,1,3.21,3.21
    3.42,1,3.42,4.11
    3.5,1,3.5,1.22
    4.1,2,4.1,9.2
    4.2,2,4.2,2.11
    

    No entanto, até onde eu sei csvtool, não moverá (ou removerá ) um arquivo namedcol.

    Se você não conseguir encontrar uma ferramenta CSV especializada, você pode criar a sua própria usando uma linguagem de uso geral, como Awk ou Perl. A ideia seria pesquisar os campos da primeira linha pelo índice da coluna correspondente e, em seguida, dividir os campos na ordem escolhida.

    Por exemplo, usando o módulo perl Text::CSV , e este truque Como obter o índice de um elemento específico (valor) de uma matriz?

    $ perl -MText::CSV -lpe '
      BEGIN{ $p = Text::CSV->new({ allow_whitespace => 1 }) };
      @f = $p->fields() if $p->parse($_);
      ($i) = grep { $f[$_] eq "value" } (0..$#f) if $. == 1; 
      $_ = join ", ", splice(@f, $i, 1),  @f
    ' example_file.txt
    value, group, price
    3.21, 1, 3.21
    3.42, 1, 4.11
    3.5, 1, 1.22
    4.1, 2, 9.2
    4.2, 2, 2.11
    
    • 4
  3. pa4080
    2019-01-21T08:36:10+08:002019-01-21T08:36:10+08:00

    Minha sugestão é o seguinte roteiro:

    #!/bin/bash
    
    # Set a default value of the LABEL of the target column that must become first column
    if [[ -z ${LABEL+x} ]]; then LABEL='value'; fi
    
    # Process a single FILE
    move_the_label_column_first() {
        # Read the LABELS on the first line of the input file as an array
        IFS=', ' read -a LABELS < <(cat "$FILE" 2>/dev/null | head -n1)
    
        # Find the number of the target column
        for ((COL = 0; COL < ${#LABELS[@]}; ++COL))
        do
            if [[ ${LABELS[$COL]} == "$LABEL" ]]
            then
                break
            fi
        done
    
        # Read each LINE from the input file as an array and output it in the new order
        while IFS=', ' read -a LINE
        do
            printf '%s, ' "${LINE[$COL]}" "${LINE[@]:0:$COL}" "${LINE[@]:$((COL + 1))}" | \
            sed 's/, $/\n/'
        done < <(cat "$FILE" 2>/dev/null)
    }
    
    # Process all input files, exclude the current script filename
    for FILE in "$@"
    do
        if [[ -f $FILE ]] && [[ $FILE != $(basename "$0") ]]
        then
            #echo "Input file: $FILE"
            move_the_label_column_first
        fi
    done
    

    Vamos chamar o script reorder.sh. Para ilustrar as capacidades do script vamos supor que existem os seguintes arquivos que queremos processar e eles estão localizados no mesmo diretório onde está nosso script.

    $ cat in-file-1 
    group, value, price
    1, 3.21, 3.21
    1, 3.42, 4.11
    1, 3.5, 1.22
    
    $ cat in-file-2
    price, group, value, other
    3.21, 1, 3.21, 7
    4.11, 1, 3.42, 13
    1.22, 1, 3.5, -1
    

    Processe um arquivo de entrada:

    $ ./reorder.sh in-file-1 
    value, group, price
    3.21, 1, 3.21
    3.42, 1, 4.11
    3.5, 1, 1.22
    

    Processe dois arquivos de entrada e altere o rótulo da coluna que deve se tornar a primeira coluna para price:

    $ LABEL='price' ./reorder.sh in-file-1 in-file-2 
    price, group, value
    3.21, 1, 3.21
    4.11, 1, 3.42
    1.22, 1, 3.5
    price, group, value, other
    3.21, 1, 3.21, 7
    4.11, 1, 3.42, 13
    1.22, 1, 3.5, -1
    

    Processe todos os arquivos no diretório:

    $ ./reorder.sh *
    value, group, price
    3.21, 1, 3.21
    3.42, 1, 4.11
    3.5, 1, 1.22
    value, price, group, other
    3.21, 3.21, 1, 7
    3.42, 4.11, 1, 13
    3.5, 1.22, 1, -1
    

    Processe recursivamente:

    $ shopt -s globstar
    $ ./reorder.sh **/*
    value, group, price
    3.21, 1, 3.21
    ...
    
    • 2
  4. Rasmus Have
    2019-12-16T15:17:17+08:002019-12-16T15:17:17+08:00

    Usá csvtool-lo pode ser feito com um pequeno wrapper de script de shell:

    # Make sure that the value column isn't in front already
    if head -n 1 example_file.txt | grep -q '^value,'; then
        # Value already in front
        exit
    fi
    
    # Calculate the position of value in the header (1-indexed, as thats what csvtool use)
    pos=$(($(head -n 1 example_file.txt | sed -e 's/, value\(,.*\|$\)//' | tr -d -c ',' | wc -c)+2))
    
    # Move the value column as the pos-position to the front
    csvtool col $pos,1-$((pos-1)),$((pos+1))- example_file.txt > example_file_fixed.txt
    

    O wrapper aqui descobre em que posição a coluna de valor está, no cabeçalho (contando vírgulas antes do valor). Em seguida, ele usa o csvtoolcomando para reorganizar as colunas em value, <columns before>, <columns after>.

    • 2

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Existe um comando para listar todos os usuários? Também para adicionar, excluir, modificar usuários, no terminal?

    • 9 respostas
  • Marko Smith

    Como excluir um diretório não vazio no Terminal?

    • 4 respostas
  • Marko Smith

    Como descompactar um arquivo zip do Terminal?

    • 9 respostas
  • Marko Smith

    Como instalo um arquivo .deb por meio da linha de comando?

    • 11 respostas
  • Marko Smith

    Como instalo um arquivo .tar.gz (ou .tar.bz2)?

    • 14 respostas
  • Marko Smith

    Como listar todos os pacotes instalados

    • 24 respostas
  • Martin Hope
    Flimm Como posso usar o docker sem sudo? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    led-Zepp Como faço para salvar a saída do terminal em um arquivo? 2014-02-15 11:49:07 +0800 CST
  • Martin Hope
    ubuntu-nerd Como descompactar um arquivo zip do Terminal? 2011-12-11 20:37:54 +0800 CST
  • Martin Hope
    TheXed Como instalo um arquivo .deb por meio da linha de comando? 2011-05-07 09:40:28 +0800 CST
  • Martin Hope
    Ivan Como listar todos os pacotes instalados 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    David Barry Como determino o tamanho total de um diretório (pasta) na linha de comando? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher "Os seguintes pacotes foram retidos:" Por que e como resolvo isso? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford Como os PPAs podem ser removidos? 2010-07-30 01:09:42 +0800 CST

Hot tag

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve