Filtrer un fichier .CSV en fonction des valeurs de la 5ème colonne d'un fichier et imprimer ces enregistrements dans un nouveau fichier

16

J'ai un fichier .CSV avec le format ci-dessous:

"column 1","column 2","column 3","column 4","column 5","column 6","column 7","column 8","column 9","column 10
"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23455","12312255564","string, with, multiple, commas","string with or, without commas","string 2","USD","433","70%","07/15/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""
"46476","15467534544","lengthy string, with commas, multiple: colans","string with or, without commas","string 2","CAND","388","70%","09/21/2013",""

La 5e colonne du fichier a différentes chaînes. J'ai besoin de filtrer le fichier en fonction de la valeur de la 5ème colonne. Disons que j'ai besoin d'un nouveau fichier du fichier actuel qui n'a que des enregistrements avec la valeur "chaîne 1" dans son cinquième champ.

Pour cela, j'ai essayé la commande ci-dessous,

awk -F"," ' { if toupper($5) == "STRING 1") PRINT }' file1.csv > file2.csv

mais il me jetait une erreur comme suit:

awk: { if toupper($5) == "STRING 1") PRINT }
awk: ^ syntax error
awk: { if toupper($5) == "STRING 1") PRINT }
awk: ^ syntax error

J'ai ensuite utilisé ce qui suit, ce qui me donne une sortie étrange.

awk -F"," '$5="string 1" {print}' file1.csv > file2.csv

Production:

"column 1" "column 2" "column 3" "column 4" string 1 "column 6" "column 7" "column 8" "column 9" "column 10
"12310" "42324564756" "a simple string with a comma" string 1 without commas" "string 1" "USD" "12" "70%" "08/01/2013" ""
"23455" "12312255564" "string with string 1 commas" "string with or without commas" "string 2" "USD" "433" "70%" "07/15/2013" ""
"23525" "74535243123" "string with commas string 1 "string with or without commas" "string 1" "CAND" "744" "70%" "05/06/2013" ""
"46476" "15467534544" "lengthy string with commas string 1 "string with or without commas" "string 2" "CAND" "388" "70%" "09/21/2013" ""

PS: J'ai utilisé la commande toupper pour être du bon côté, car je ne suis pas sûr que la chaîne soit en minuscule ou en majuscule. J'ai besoin de savoir ce qui ne va pas avec mon code et si l'espace dans la chaîne compte lors de la recherche d'un modèle à l'aide d'AWK.

Dhruuv
la source

Réponses:

17
awk -F '","'  'BEGIN {OFS=","} { if (toupper($5) == "STRING 1")  print }' file1.csv > file2.csv 

Production

"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""

Je pense que c'est ce que vous voulez.

limovala
la source
La sortie est exactement ce dont j'avais besoin. Je n'ai pas pensé à faire '","'comme délimiteur, sinon cela aurait résolu mon problème ... excellente solution ...
Dhruuv
@Dhruuv faisant '","'le délimiteur est ce que la plupart des réponses à votre question précédente suggéraient :).
terdon
@terdon: oui, je sais, mais cela ne m'est pas venu à l'esprit lorsque j'ai eu le problème. Franchement, je pensais que ce serait peut - être quelque chose avec la commande ou autre chose que les délimiteurs qui a été l' origine du problème ... :) Par conséquent n'a pas donné d'essayer ... :(
Dhruuv
2
@Dhruuv n'est pas sûr des détails car je ne peux pas dire ce que vous essayez de faire mais votre autre condition est presque certainement fausse. Essayez-vous d'imprimer uniquement si 5 $ est HYPERION? Si oui, essayez else{if(toupper($5)=="HYPERION"){print}}. Pas sur mon ordinateur pour le moment, donc je peux avoir une mauvaise syntaxe mais vous ne pouvez pas donner de condition à une instruction else.
terdon
1
awk -F '","' 'BEGIN {OFS=","} { if (NR==1) {print} else{if (toupper($5) == "STRING 1") print} }' file1
limovala
2

Le problème avec CSV est qu'il n'y a pas de norme. Si vous devez souvent traiter des données au format CSV, vous souhaiterez peut-être rechercher une méthode plus robuste plutôt que de simplement l'utiliser ","comme séparateur de champ. Dans ce cas, les Text::CSVmodules CPAN de Perl sont exceptionnellement bien adaptés à la tâche:

$ perl -mText::CSV_XS -WlanE '
    BEGIN {our $csv = Text::CSV_XS->new;} 
    $csv->parse($_); 
    my @fields = $csv->fields(); 
    print if $fields[4] =~ /string 1/i;
' file1.csv
"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""

la source
-1
awk 'BEGIN {FS = "," }'  '{ (if toupper($5)  == "STRING 1") print; }'  file1.csv > file2.csv
Golfe Persique
la source
Désolé de le dire, mais votre solution ne renvoie aucun enregistrement du fichier ... Je pense que l'ajout du délimiteur '","'fera l'affaire ... merci ... :)
Dhruuv
@Mohsen -1 car 1) vous devez échapper au "ou ils ne sont pas compris comme des parties du délimiteur de fichier. Voir les réponses à l'autre question de l'OP et 2) vous séparez le bloc BEGIN du reste de la commande qui complètement essayez awk 'BEGIN {FS = "," }' '{print $0}', vous verrez qu'il ne produit aucune sortie. À l'avenir, veuillez tester vos réponses pour voir si elles fonctionnent réellement avant de les publier.
terdon