Mude o formato da moeda para o número genérico usando sed

2

Estou trabalhando em um grande arquivo csv com todas as entradas separadas por coma. O documento inteiro é composto por números simples, exceto por algumas colunas que refletem moedas formatadas como texto. Por exemplo, uma dessas entradas pode parecer com "$12,345.67" e outra como "$1,234,567.89" (os símbolos de aspas duplas também são incluídos como parte das entradas). Aqui está um exemplo de um registro completo (uma única linha) de dados:

123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2

Eu gostaria de fazer algum processamento neste arquivo de dados e, portanto, quero reformatar esses campos de texto para se tornarem números simples (ou seja, se livrando de aspas duplas e comas). Eu acho que um substituto de padrão de regex com sed deve fazer o trabalho para mim, mas não tenho certeza de como é essa expressão regular. Qualquer ideia seria muito apreciada.

    
por Ali 10.10.2012 / 01:59

4 respostas

1

é simples expressar o que deve ser feito:

1 Para cada cadeia que está entre "$ e " , exclua todos os ,
   2 elimine o "$ e "

Isso são expressões sed. Se você usá-lo na roupa de comando, você deve citá-lo apropriadamente. É mais simples colocá-lo em um arquivo, por exemplo command.sed e chame por

sed -f command.sed data.csv

Este é o programa que implementa os dois passos:

:repeat
s/"\$\([^,"]*\),/"$/g 
t repeat
s/"\$\([^"]*\)"//g 

Este documento ajudou-me a resolver o problema.

    
por 10.10.2012 / 10:24
1

Atualização: adaptando a resposta de Substitua os espaços apenas entre aspas para lidar com esse problema.

Comando:

echo '123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2' |
awk -F\" '{OFS="\""; for (i = 2; i < NF; i += 2) gsub(/[$,]/,"",$i); gsub(/"/,""); print}'

Saída:

123,7,11,343700.14,34928.63,377000.00,15421.92,19,2

O primeiro gsub remove $ s e , s entre aspas duplas. O segundo remove as citações.

Deixando a resposta original abaixo, caso isso ajude.

Se eu entendi corretamente uma pesquisa simples e substituir faria

echo '"$1,234,567.89"' | sed 's/[$,"]//g'

Saída 1234567.89 .

O que isto significa é que ele substitui ( s ) os caracteres correspondentes ( [] ) $ , , e " com nada (vazio entre os dois últimos / . O g flag faz com que seja aplicado globalmente, substituindo todas as instâncias (caso contrário, apenas a primeira instância de uma linha seria substituída).

Como aplicar isso ao arquivo inteiro depende do formato do arquivo. Se não houver mais nada no arquivo que tenha aspas duplas, cifrões e vírgula, isso deve ser bom:

sed 's/[$,"]//g' /path/to/file
    
por 10.10.2012 / 02:17
0

Como esse valor monetário é exibido depende do seu visualizador de CSV, por que você não alteraria a "visualização", por exemplo, no Excel, em vez de alterar este campo?

YAnyway, você pode ter vários campos em seu campo csv, portanto, seria mais seguro usar um script de manipulador como este:

#!/usr/bin/perl

use strict;
use warnings;
use Text::CSV;

my $csv = Text::CSV->new ( { binary => 1 } );
while ( my $row = $csv->getline(\*STDIN) ) {
    foreach my $item (@$row)
    {
        $item =~ s/,//g if ($item =~ /^\$[0-9,.]+$/);
    }
    $csv->print (\*STDOUT, $row);
    print "\n";
}

Uso: ./csv.pl < in.csv > ou.csv

Entrada:

abc,"$1,243,311.99",def
abc2,"$43,311.99",def2

Saída:

abc,$1243311.99,def
abc2,$43311.99,def2
    
por 10.10.2012 / 02:27
0

Uma solução awk ligeiramente complicada, baseada em análise de CSV com o awk

{
$0=$0",";                                  # yes, cheating
while($0) {
  gsub(/\$/,"",$0)
  match($0,/ *"[^"]*" *,|[^,]*,/);
  sf=f=substr($0,RSTART,RLENGTH);          # save what matched in sf
  gsub(/^ *"?|"? *,$/,"",f);               # remove extra stuff
  gsub(/,/,"",f);
  if($0 ~ /,[^,]+,$/){
    printf "%s,",f;
  }else{
    printf "%s",f;
  }
  sub(sf,"");                              # "consume" what matched
}
printf "\n"
}

Salva o acima como csv.awk e correu assim:

echo '123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2'|awk -f csv.awk
123,7,11,343700.14,34928.63,377000.00,15421.92,19,2
    
por 10.10.2012 / 04:53