Question

J'importe des données d'un CSV fichier et les nombres supérieurs à 1000 se transformer en 1,100 etc.

Quelle est la bonne façon de supprimer à la fois les guillemets et la virgule afin que je puisse les mettre dans un int champ?

Modifier:

Les données sont en fait déjà dans une table MySQL, je dois donc pouvoir le faire en utilisant SQL.Désolé pour la confusion.

Était-ce utile?

La solution

Voici un bon cas pour les expressions régulières.Vous pouvez exécuter une recherche et un remplacement sur les données avant de les importer (plus facile) ou plus tard si l'importation SQL a accepté ces caractères (pas aussi simple).Mais dans les deux cas, vous disposez d'un certain nombre de méthodes pour effectuer une recherche et un remplacement, qu'il s'agisse d'éditeurs, de langages de script, de programmes GUI, etc.N'oubliez pas que vous allez vouloir rechercher et remplacer tous des mauvais personnages.

Une expression régulière typique pour trouver la virgule et les guillemets (en supposant uniquement des guillemets doubles) est : (Liste noire)

/[,"]/

Ou, si vous constatez que quelque chose pourrait changer à l'avenir, cette expression régulière correspond à tout sauf un nombre ou un point décimal. (Liste blanche)

/[^0-9\.]/

Ce qui a été discuté par les personnes ci-dessus, c'est que nous ne connaissons pas toutes les données de votre fichier CSV.Il semble que vous souhaitiez supprimer les virgules et les guillemets de tous les nombres du fichier CSV.Mais comme nous ne savons pas ce qu'il y a d'autre dans le fichier CSV, nous voulons nous assurer de ne pas corrompre d'autres données.Le simple fait d'effectuer aveuglément une recherche/remplacement pourrait affecter d'autres parties du fichier.

Autres conseils

Je suppose que, parce que les données ont pu être importées, le champ est en fait un varchar ou un champ de caractères, car l'importation dans un champ numérique a peut-être échoué.Voici un cas de test dans lequel j'ai exécuté uniquement une solution MySQL et SQL.

  1. Le tableau n'est qu'une seule colonne (alpha) qui est un varchar.

    mysql> desc t;
    
    +-------+-------------+------+-----+---------+-------+
    | Field | Type        | Null | Key | Default | Extra |
    +-------+-------------+------+-----+---------+-------+
    | alpha | varchar(15) | YES  |     | NULL    |       | 
    +-------+-------------+------+-----+---------+-------+
    
  2. Ajouter un enregistrement

    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. Mettre à jour la déclaration.

    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 | 
    +---------+
    

Donc à la fin, la déclaration que j'ai utilisée était :

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

J'ai regardé le Documentation MySQL et il ne semblait pas que je puisse trouver les expressions régulières et remplacer.Même si tu pourrais, comme Eldila, utilisez une expression régulière pour rechercher, puis une solution alternative pour remplacer.


Soyez également prudent avec s/"(\d+),(\d+)"/$1$2/ car que se passe-t-il si le nombre contient plus d'une simple virgule, par exemple "1 000 000", vous souhaiterez effectuer un remplacement global (en Perl, c'est s///g).Mais même avec un remplacement global, le remplacement commence là où vous vous êtes arrêté (sauf si Perl est différent) et manquerait tous les autres groupes séparés par des virgules.Une solution possible serait de rendre le premier (\d+) facultatif comme ceci s/(\d+)?,(\d+)/$1$2/g et dans ce cas, j'aurais besoin d'une deuxième recherche et remplacement pour supprimer les guillemets.

Voici quelques exemples rubis d'expressions régulières agissant uniquement sur la chaîne "1 000 000", remarquez qu'il n'y a PAS de guillemets doubles à l'intérieur de la chaîne, il s'agit simplement d'une chaîne du nombre lui-même.

>> "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"

Vous pouvez utiliser cette commande Perl.

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

Vous devrez peut-être jouer un peu avec, mais cela devrait faire l'affaire.

Voici la méthode PHP :

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

Lien vers la page W3Schools

En fait, nlucaroni, votre cas n'est pas tout à fait correct.Votre exemple n'inclut pas de guillemets doubles, donc

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

ne correspondra pas à mon regex.Il nécessite le format "XXX,XXX".Je ne peux pas penser à un exemple de cas où cela ne correspondra pas correctement.

Tous les exemples suivants n'incluront pas le délimiteur dans l'expression régulière :

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

S'il vous plaît laissez-moi savoir si vous pouvez penser à un contre-exemple.

Acclamations!

La solution à la question modifiée est fondamentalement la même.

Vous devrez exécuter une requête de sélection avec la clause regex Where.

Quelque chose comme

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

Pour chacune de ces lignes, vous souhaitez effectuer la substitution d'expression régulière suivante s/"(\d+),(\d+)"/$1$2/, puis mettre à jour le champ avec la nouvelle valeur.

S'il vous plaît Joseph Pecoraro sérieusement et faites une sauvegarde avant d'apporter des modifications massives à des fichiers ou des bases de données.Parce que chaque fois que vous effectuez une expression régulière, vous pouvez sérieusement gâcher les données si vous avez manqué certains cas.

Ma commande supprime tous les ',' et '"'.

Afin de convertir plus strictement le sting "1 000", vous aurez besoin de la commande suivante.

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

La réponse de Daniel et Eldila pose un problème :Ils suppriment tous les guillemets et virgules de l’ensemble du fichier.

Ce que je fais habituellement lorsque je dois faire quelque chose comme ça, c'est d'abord remplacer tous les guillemets de séparation et (généralement) les points-virgules par des tabulations.

  • Recherche: ";"
  • Remplacer:

Puisque je sais dans quelle colonne seront mes valeurs concernées, je fais ensuite une autre recherche et remplace :

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

...étant donné que la valeur avec la virgule est dans la troisième colonne.

Vous devez commencer par un "^" pour vous assurer qu'il commence au début d'une ligne.Ensuite, vous répétez ([0-9]+) aussi souvent qu'il y a des colonnes que vous souhaitez simplement laisser telles quelles.

([0-9]+),([0-9]+) recherche les valeurs où il y a un nombre, puis une virgule et enfin un autre nombre.

Dans la chaîne de remplacement, nous utilisons \1 et \2 pour conserver simplement les valeurs de la ligne modifiée, en les séparant par (tabulation).Ensuite, nous mettons \3\4 (pas de tabulation entre) pour mettre les deux composantes du nombre sans la virgule l'une après l'autre.Toutes les valeurs ultérieures seront laissées telles quelles.

Si vous avez besoin que votre fichier ait un point-virgule pour séparer les éléments, vous pouvez alors continuer et remplacer les tabulations par des points-virgules.Cependant, si vous omettez les guillemets, vous devrez vous assurer que les valeurs de texte ne contiennent pas elles-mêmes de point-virgule.C'est pourquoi je préfère utiliser TAB comme séparateur de colonnes.

Je fais généralement cela dans un éditeur de texte ordinaire (EditPlus) prenant en charge RegExp, mais les mêmes expressions rationnelles peuvent être utilisées dans n'importe quel langage de programmation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top