3
votes

Comparer les lignes d'un fichier dans bash

fichier input.txt

12345678,Manoj,23,Developer,0000019
12345678,Manoj,34,Developer,0000020
12345678,Manoj,67,Developer,0000021
12345679,Vijay,12,Tester,0000019
12345679,Vijay,98,Tester,0000020
12345676,Samrat,100,Manager,0000019
12345676,Samrat,25,Manager,0000020
12345676,Samrat,28,Manager,0000021

Fichier de sortie souhaité

12345678,Manoj,23,Developer,0000000
12345678,Manoj,34,Developer,0000001
12345678,Manoj,67,Developer,0000002
12345679,Vijay,12,Tester,0000000
12345679,Vijay,98,Tester,0000001
12345676,Samrat,100,Manager,0000000
12345676,Samrat,25,Manager,0000001
12345676,Samrat,28,Manager,0000002

Explication[

Ici, la première valeur, c'est-à-dire 12345678 dans les 3 premières lignes de mon fichier d'entrée est la même, alors ajoutez les 3 premières lignes avec, 0, 1 et, 2 respectivement. Et de la même manière que les lignes suivantes.

Comment cela peut être fait dans Shell Script.

Modifier dans la sortie souhaitée

Est-il également possible de changer le format de numéro de sortie souhaitée pour le suivant pour la sortie?

12345678,Manoj,23,Developer,0
12345678,Manoj,34,Developer,1
12345678,Manoj,67,Developer,2
12345679,Vijay,12,Tester,0
12345679,Vijay,98,Tester,1
12345676,Samrat,100,Manager,0
12345676,Samrat,25,Manager,1
12345676,Samrat,28,Manager,2

Nouveau: Est-il possible de commencer la numérotation à partir de 0000019. Existe-t-il une autre option pour initialiser une variable comme a = 5, a = 19, a = 39 à partir de laquelle je peux incrémenter par la suite.

12345678,Manoj,23,Developer
12345678,Manoj,34,Developer
12345678,Manoj,67,Developer
12345679,Vijay,12,Tester
12345679,Vijay,98,Tester
12345676,Samrat,100,Manager
12345676,Samrat,25,Manager
12345676,Samrat,28,Manager


2 commentaires

Ne modifiez PAS le contenu de votre question après qu'une réponse ou des commentaires ont été fournis. Cela rend toutes les réponses et commentaires avant votre modification plus valides. Modifiez plutôt votre question et AJOUTEZ les ajouts au bas de votre question. De cette façon, les réponses et les commentaires resteront valables. (vous obtenez un cadeau pour ne pas savoir, mais ajoutez la prochaine fois :)


Noté @ DavidC.Rankin


4 Réponses :


7
votes

Utilisation de awk:

$ awk '
BEGIN { 
    FS=","
    # ORS="\r\n"                     # uncomment if Windows line-endings are desired
}      
{
    sub(/\r$/,"")                    # remove Windows line-endings (ie. \r from \r\n)
    printf "%s,%07d" ORS,$0,a[$1]++  # output zeropadded running count on $1
}' file

Résultat:

$ awk 'BEGIN{FS=","}{sub(/\r$/,"");printf "%s,%07d" ORS,$0,a[$1]++}' file

Modifier :

Comme les exigences ont changé et que beaucoup de commentaires ont eu lieu, voici la version finale (révision 1 car les exigences étaient différentes dans les commentaires et l'OP, frappant au bois):

12345678,Manoj,23,Developer,0
12345678,Manoj,34,Developer,1
12345678,Manoj,67,Developer,2
12345679,Vijay,12,Tester,0
12345679,Vijay,98,Tester,1
12345676,Samrat,100,Manager,0
12345676,Samrat,25,Manager,1
12345676,Samrat,28,Manager,2

Expliqué:

$ awk 'BEGIN{FS=OFS=",";RS="\r?\n"}{print $0,a[$1]++}' file

Testé avec gawk, mawk, busybox awk et l'original-awk (awk version 20121220). Oh, et recyclé ma boîte Solaris il y a 5 ans. ; D


16 commentaires

, 0345678, Manoj, 002, Développeur, 1345678, Manoj, 002, Développeur, 2345678, Manoj, 002, Développeur. Les valeurs sont ajoutées au début. j'ai besoin que les valeurs soient ajoutées à la fin.


Il est. Vous avez probablement des fins de ligne Windows dans le fichier ( \ r \ n) . Corrigé avec RS = "\ r? \ N" .


12345678, Manoj, 23 ans, développeur, 0000000 12345678, Manoj, 34 ans, développeur, 0000001 12345678, Manoj, 67 ans, développeur, 0000002. Cette modification est-elle possible.


{printf "% s,% 07d \ n", $ 0, a [$ 1] ++} (bravo @JamesBrown)


12345678, Manoj, 23, Développeur, 0000000 12345678, Manoj, 34, Développeur, 0000001 12345678, Manoj, 67, Développeur, 0000002 12345679, Vijay, 12, Tester, 0000003 12345679, Vijay, 98, Tester, 0000004 12345676, Samrat, 100 , Directeur, 0000005 12345676, Samrat, 25 ans, Directeur, 0000006 12345676, Samrat, 28 ans, Directeur, 0000007. Cette modification est-elle possible sans comparer les premières valeurs de toutes les lignes


{printf "% s,% 07d \ n", $ 0, a ++}


@Manoj Juste un numéro courant après l'enregistrement? Bien sûr, remplacez print par printf "% s,% 08d \ n", $ 0, NR .


Voyez, vous pouvez le faire. En attendant que vous commenciez à répondre à ces questions avec nous!


Je ferai bien sûr ... James


Quelques commentaires ici: (1) L'utilisation de RS = "\ r? \ N" n'est pas POSIX et cela ne fonctionnera que sur quelques versions de awk (principalement gawk). (2) Très probablement, le fichier dos devrait redevenir un fichier dos, actuellement, les fins de ligne ne seront que "\ n". Vous pouvez utiliser printf et RT au lieu de print qui ajoute le ORS par défaut (3) Il n'y a pas besoin de définir FS . ( awk 'BEGIN {RS = "\ r? \ n"} {printf "% s,% 0.7d" RT; $ 0, un fichier [$ 1] ++}' )


@JamesBrown Je sais que vous connaissez la plupart de cela, je viens de l'écrire comme un commentaire général pour les personnes qui lisent votre réponse.


Testé avec succès avec gawk, mawk et busybox awk, sans succès avec le "awk original" fourni avec Debian.


@JamesBrown est bon de savoir que ces 3 cas fonctionnent. Le awk de Solaris échoue. Posix n'attend qu'un seul caractère comme RS et non un BRE .


Quelle est la façon de commencer la numérotation à partir de 00000001 au lieu de 00000000


awk 'BEGIN {FS = ","} {sub (/ \ r $ /, ""); printf "% s,% 07d" ORS, $ 0, ++ a [$ 1]}' fichier ie. ++ a [$ 1] au lieu de a [$ 1] ++ .


Compris. Merci pour la réponse rapide. Mais le numéro de départ varie de 00000001, 00000020, 00000039. Existe-t-il une autre option pour initialiser une variable comme a = 1, a = 20, a = 39 d'où je peux incrémenter par la suite.



2
votes

Mettre à jour pour corriger mon ancienne erreur de fin de ligne auto-inconnue .

Utilisez ceci, fonctionnera sur les deux \ r \ n et \ n fins de ligne, la sortie se terminera par \n:

ruby -aF, -pe 'BEGIN{a=Hash.new(18)};sub(/\r?$/, "," + "%07d" % a[$F[1]]+=1)' input.txt

Sortie:

awk 'sub(/\r$/,"") ($(NF+1)=sprintf("%07d",19+a[$2]++))' FS=, OFS=, input.txt

J'ai écrit comme ça pour plus de concision, c'est fonctionnellement égal à:

ruby -aF, -pe 'BEGIN{a=Hash.new(-1)};sub(/\r?$/, "," + "%07d" % a[$F[1]]+=1)' input.txt

Si vous avoir ruby ​​ installé:

awk 'BEGIN{FS=OFS=","}{sub(/\r$/,"");$(NF+1)=sprintf("%07d",a[$2]++)}1' input.txt

Même sortie.

Btw, si vous voulez qu'il commence par 19, vous pouvez utiliser ceci (ajoutez 19+ à la valeur):

12345678,Manoj,23,Developer,0000000
12345678,Manoj,34,Developer,0000001
12345678,Manoj,67,Developer,0000002
12345679,Vijay,12,Tester,0000000
12345679,Vijay,98,Tester,0000001
12345676,Samrat,100,Manager,0000000
12345676,Samrat,25,Manager,0000001
12345676,Samrat,28,Manager,0000002

Ou ceci (initialiser avec 18):

awk -F, 'sub(/\r$/,"") ($(NF+1)=sprintf("%07d",a[$2]++))' OFS=, input.txt


0 commentaires

1
votes

Pourriez-vous s'il vous plaît essayer ci-dessous. (sans modifier la ligne, imprimez-la simplement avec une valeur supplémentaire de nombre de tableaux)

awk 'BEGIN{FS=OFS=","} {printf("%s,%07d\n",$0,count[$2]++)}' Input_file


1 commentaires

@Manoj, pourriez-vous s'il vous plaît me faire savoir la raison pour laquelle ma réponse est supprimée ici?



1
votes

Utilisation de Perl

$ cat manoj.txt
12345678,Manoj,23,Developer
12345678,Manoj,34,Developer
12345678,Manoj,67,Developer
12345679,Vijay,12,Tester
12345679,Vijay,98,Tester
12345676,Samrat,100,Manager
12345676,Samrat,25,Manager
12345676,Samrat,28,Manager
$ perl -F, -lane ' $F[$#F]=~s/\r//g; $F[$#F+1]=sprintf("%07d",$kv{$F[0]}++);$,=",";  print @F ' manoj.txt
12345678,Manoj,23,Developer,0000000
12345678,Manoj,34,Developer,0000001
12345678,Manoj,67,Developer,0000002
12345679,Vijay,12,Tester,0000000
12345679,Vijay,98,Tester,0000001
12345676,Samrat,100,Manager,0000000
12345676,Samrat,25,Manager,0000001
12345676,Samrat,28,Manager,0000002
$


1 commentaires

pouvez-vous expliquer cela? je ne connais pas la variable $ kv , merci