15
votes

Suppression de plusieurs délimiteurs entre les délimiteurs extérieurs sur chaque ligne

En utilisant awk ou sed dans un script bash, je dois supprimer les délimiteurs séparés par des virgules qui sont situés entre un délimiteur interne et externe. Le problème est que de mauvaises valeurs se retrouvent dans les mauvaises colonnes, où seules 3 colonnes sont souhaitées.

Par exemple, je veux tourner ceci:

2020/11/04,Test Account,569.00
2020/11/05,Test Account,250.00
2020/11/05,More Test Accounts,225.00

Dans ceci:

2020/11/04,Test Account,569.00
2020/11/05,Test,Account,250.00
2020/11/05,More,Test,Accounts,225.00

J'ai essayé d'utiliser quelques choses, en testant regex: mais je ne trouve pas de solution pour sélectionner uniquement les virgules afin de supprimer.

exemple regexr


0 commentaires

6 Réponses :


7
votes

awk ne prend pas en charge le look arounds, nous pourrions l'avoir en utilisant la fonction match de awk ; en utilisant cela, vous pouvez essayer de suivre, écrit et testé avec les exemples présentés dans GNU awk .

awk '
match($0,/,.*,/){
  val=substr($0,RSTART+1,RLENGTH-2)
  gsub(/,/," ",val)
  print substr($0,1,RSTART) val substr($0,RSTART+RLENGTH-1)
}
' Input_file


2 commentaires

Merci pour votre réponse. Piping echo to awk J'obtiens une erreur de syntaxe sur 'print' et sur 'val = ""'


@AJHart, selon vos échantillons affichés, il semble que ce soit un fichier_entrée, alors copiez / collez cette commande dans le terminal de votre boîte et donnez votre nom de fichier réel où Input_file est donné, celui-ci est testé avec succès, faites-moi savoir si des requêtes sont là .



9
votes
awk -F, '{ printf "%s,",$1;for (i=2;i<=NF-2;i++) { printf "%s ",$i };printf "%s,%s\n",$(NF-1),$NF }' file
Using awk, print the first comma delimited field and then loop through the rest of the field up to the last but 2 field printing the field followed by a space. Then for the last 2 fields print the last but one field, a comma and then the last field.

0 commentaires

10
votes

Avec GNU awk pour le 3ème argument à correspondre ():

$ awk '
    BEGIN { FS=OFS="," }
    {
        n = split($0,a)
        gsub(/^[^,]*,|,[^,]*$/,"")
        gsub(/,/," ")
        print a[1], $0, a[n]
    }
' file
2020/11/04,Test Account,569.00
2020/11/05,Test Account,250.00
2020/11/05,More Test Accounts,225.00

ou avec n'importe quel awk:

$ awk -v OFS=, '{
     match($0,/([^,]*),(.*),([^,]*)/,a)
     gsub(/,/," ",a[2])
     print a[1], a[2], a[3]
}' file
2020/11/04,Test Account,569.00
2020/11/05,Test Account,250.00
2020/11/05,More Test Accounts,225.00


0 commentaires

6
votes

Utilisez ce one-liner Perl:

perl -F',' -lane 'print join ",", $F[0], "@F[1 .. ($#F-1)]", $F[-1];' in.csv

Le one-liner Perl utilise ces indicateurs de ligne de commande:
-e : indique à Perl de rechercher du code en ligne, plutôt que dans un fichier.
-n : boucle sur l'entrée une ligne à la fois, en l'affectant à $_ par défaut.
-l : Supprimez le séparateur de ligne d'entrée ( "\n" sur * NIX par défaut) avant d'exécuter le code en ligne et ajoutez-le lors de l'impression.
-a : @F $_ en tableau @F sur un espace ou sur l'expression régulière spécifiée dans l'option -F .
-F',' : Split en @F sur virgule, plutôt que sur des espaces.

$F[0] : premier élément du tableau @F (= première valeur délimitée par des virgules).
$F[-1] : dernier élément de @F .
@F[1 .. ($#F-1)] : éléments de @F entre le second depuis le début et le second depuis la fin, inclus.
"@F[1 .. ($#F-1)]" : les éléments ci-dessus, joints sur des blancs dans une chaîne.
join ",", ... : joindre la LISTE " ... " par une virgule, et renvoyer la chaîne résultante.

VOIR ÉGALEMENT:
perldoc perlrun : comment exécuter l'interpréteur Perl: commutateurs de ligne de commande


0 commentaires

7
votes
awk '{for (i=2; i<=NF; ++i) $i=(i>2 && i<NF ? " " : ",") $i} 1' FS=, OFS= file

0 commentaires

7
votes

Encore un autre perl

sed -E 's/,/\n/; s/,([^,]*)$/\n\1/; y/,/ /; y/\n/,/'
  • (?:^[^,]*,|,[^,]*$) correspond au premier / dernier champ avec la virgule
    • (*SKIP)(*F) cela empêcherait la modification de l'expression rationnelle précédente
  • |, fournir , comme autre expression rationnelle à rechercher pour la modification

Avec sed (en supposant que \n est pris en charge par l'implémentation, sinon, vous devrez trouver un caractère qui ne peut pas être présent dans l'entrée)

$ perl -pe 's/(?:^[^,]*,|,[^,]*$)(*SKIP)(*F)|,/ /g' ip.txt
2020/11/04,Test Account,569.00
2020/11/05,Test Account,250.00
2020/11/05,More Test Accounts,225.00
  • s/,/\n/; s/,([^,]*)$/\n\1/ remplacer la première et la dernière virgule par le caractère de nouvelle ligne
  • y/,/ / remplace toutes les virgules par un espace
  • y/\n/,/ changer les nouvelles lignes en virgule


0 commentaires