Pergunta

Estou importando alguns dados de um CSV arquivo e números maiores que 1000 se transformar em 1,100 etc.

Qual é uma boa maneira de remover as aspas e a vírgula para que eu possa colocá-lo em um int campo?

Editar:

Na verdade, os dados já estão em uma tabela MySQL, então preciso fazer isso usando SQL.Desculpe pela confusão.

Foi útil?

Solução

Aqui está um bom caso para expressões regulares.Você pode executar uma localização e substituição nos dados antes da importação (mais fácil) ou mais tarde, se a importação SQL aceitar esses caracteres (não tão fácil).Mas em ambos os casos, você tem vários métodos para localizar e substituir, sejam editores, linguagens de script, programas GUI, etc.Lembre-se de que você vai querer encontrar e substituir todos dos maus personagens.

Uma expressão regular típica para encontrar vírgula e aspas (assumindo apenas aspas duplas) é: (Lista negra)

/[,"]/

Ou, se você descobrir que algo pode mudar no futuro, esta expressão regular corresponde a qualquer coisa, exceto um número ou ponto decimal. (Lista de permissões)

/[^0-9\.]/

O que foi discutido pelas pessoas acima é que não conhecemos todos os dados do seu arquivo CSV.Parece que você deseja remover vírgulas e aspas de todos os números do arquivo CSV.Mas como não sabemos o que mais está no arquivo CSV, queremos ter certeza de não corromper outros dados.Apenas fazer uma localização/substituição cegamente pode afetar outras partes do arquivo.

Outras dicas

Meu palpite aqui é que, como os dados foram importados, o campo é na verdade um varchar ou algum campo de caractere, porque a importação para um campo numérico pode ter falhado.Aqui estava um caso de teste que executei puramente uma solução MySQL, SQL.

  1. A tabela é apenas uma única coluna (alfa) que é um varchar.

    mysql> desc t;
    
    +-------+-------------+------+-----+---------+-------+
    | Field | Type        | Null | Key | Default | Extra |
    +-------+-------------+------+-----+---------+-------+
    | alpha | varchar(15) | YES  |     | NULL    |       | 
    +-------+-------------+------+-----+---------+-------+
    
  2. Adicionar um registro

    mysql> insert into t values('"1,000,000"');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from t;
    
    +-------------+
    | alpha       |
    +-------------+
    | "1,000,000" | 
    +-------------+
    
  3. Declaração de atualização.

    mysql> update t set alpha = replace( replace(alpha, ',', ''), '"', '' );
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> select * from t;
    
    +---------+
    | alpha   |
    +---------+
    | 1000000 | 
    +---------+
    

Então, no final, a declaração que usei foi:

UPDATE table
   SET field_name = replace( replace(field_name, ',', ''), '"', '' );

Eu olhei para o Documentação MySQL e não parecia que eu conseguiria encontrar expressões regulares e substitua.Embora você pudesse, como Eldila, use uma expressão regular para encontrar e, em seguida, uma solução alternativa para substituir.


Também tome cuidado com s/"(\d+),(\d+)"/$1$2/ porque e se o número tiver mais do que apenas uma vírgula, por exemplo "1.000.000", você vai querer fazer uma substituição global (em perl, isso é s///g).Mas mesmo com uma substituição global, a substituição começa de onde você parou (a menos que perl seja diferente) e perderia todos os outros grupos separados por vírgula.Uma possível solução seria tornar o primeiro (\d+) opcional assim s/(\d+)?,(\d+)/$1$2/g e, neste caso, eu precisaria de uma segunda localização e substituição para retirar as aspas.

Aqui estão alguns exemplos Ruby de expressões regulares agindo apenas na string "1.000.000", observe que NÃO há aspas duplas dentro da string, esta é apenas uma string do próprio número.

>> "1,000,000".sub( /(\d+),(\d+)/, '\1\2' )
# => "1000,000"  
>> "1,000,000".gsub( /(\d+),(\d+)/, '\1\2' )
# => "1000,000"  
>> "1,000,000".gsub( /(\d+)?,(\d+)/, '\1\2' )
# => "1000000"  
>> "1,000,000".gsub( /[,"]/, '' )
# => "1000000"  
>> "1,000,000".gsub( /[^0-9]/, '' )
# => "1000000"

Você poderia usar este comando perl.

Perl -lne 's/[,|"]//; print' file.txt > newfile.txt

Você pode precisar brincar um pouco com isso, mas deve funcionar.

Aqui está o jeito do PHP:

$stripped = str_replace(array(',', '"'), '', $value);

Link para a página W3Schools

Na verdade, nlucaroni, seu caso não está certo.Seu exemplo não inclui aspas duplas, então

id,age,name,...
1,23,phil,

não corresponderá ao meu regex.Requer o formato "XXX,XXX".Não consigo pensar em um exemplo de quando a correspondência será incorreta.

Todos os exemplos a seguir não incluirão o delimitador na regex:

"111,111",234
234,"111,111"
"111,111","111,111"

Por favor, deixe-me saber se você consegue pensar em um contra-exemplo.

Saúde!

A solução para a questão alterada é basicamente a mesma.

Você terá que executar a consulta select com a cláusula regex where.

Algo como

Select *
  FROM SOMETABLE
  WHERE SOMEFIELD REGEXP '"(\d+),(\d+)"'

Para cada uma dessas linhas, você deseja fazer a seguinte substituição de regex s/"(\d+),(\d+)"/$1$2/ e então atualizar o campo com o novo valor.

Por favor, Joseph Pecoraro seriamente e faça um backup antes de fazer alterações em massa em qualquer arquivo ou banco de dados.Porque sempre que você faz regex, você pode bagunçar seriamente os dados se houver casos que você perdeu.

Meu comando remove todos os ',' e '"'.

Para converter o sting “1.000” de forma mais estrita, você precisará do seguinte comando.

Perl -lne 's/"(\d+),(\d+)"/$1$2/; print' file.txt > newfile.txt

A resposta de Daniel e Eldila tem um problema:Eles removem todas as aspas e vírgulas de todo o arquivo.

O que normalmente faço quando preciso fazer algo assim é primeiro substituir todas as aspas de separação e (geralmente) ponto-e-vírgula por tabulações.

  • Procurar: ";"
  • Substituir:

Como sei em qual coluna estarão meus valores afetados, faço outra pesquisa e substituo:

  • Procurar: ^([ ]+) ([ ]+) ([0-9]+),([0-9]+)
  • Substituir: \1 \2 \3\4

...dado o valor com a vírgula está na terceira coluna.

Você precisa começar com um "^" para ter certeza de que começa no início de uma linha.Então você repete ([0-9]+) quantas vezes houver colunas que você deseja deixar como estão.

([0-9]+),([0-9]+) procura valores onde há um número, depois uma vírgula e depois outro número.

Na string de substituição usamos \1 e \2 apenas para manter os valores da linha editada, separando-os com (tab).Em seguida, colocamos \3\4 (sem tabulação entre) para colocar os dois componentes do número sem a vírgula um após o outro.Todos os valores depois disso serão deixados de lado.

Se você precisar que seu arquivo tenha ponto e vírgula para separar os elementos, você pode substituir as guias por ponto e vírgula.No entanto, então - se você deixar as aspas de fora - você terá que se certificar de que os valores do texto não contêm ponto-e-vírgula.É por isso que prefiro usar TAB como separador de colunas.

Normalmente faço isso em um editor de texto comum (EditPlus) que suporta RegExp, mas os mesmos regexps podem ser usados ​​em qualquer linguagem de programação.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top