2010-12-02 11 views
1

J'ai le fichier suivant avec 4 champs. Il y a 3 groupes dans le champ 2, et le 4ème champ est constitué de 0 et de 1.Sélection des n premières lignes par groupes en utilisant AWK

Le premier champ est juste l'index.

J'aime utiliser AWK pour faire la tâche suivante

  1. Sélectionnez les 3 premiers rangs du groupe 1 (Notez que le groupe 1 ne dispose que de 2 lignes). Le nombre de lignes est basé sur le nombre de 1 trouvées dans le 4ème champ multiplié par 3.

  2. Sélectionnez les 6 premières rangées du groupe 2. Le nombre de rangées est basé sur le nombre de 1 trouvées dans le 4e champ 3.

  3. Sélectionnez les 9 premiers rangs du groupe 3. le nombre de lignes est basé sur le nombre de 1 trouvé dans le 4ème fois le champ 3.

donc 17 lignes sont sélectionnées pour la sortie fichier.

Nous vous remercions de votre aide.

Input 

1 1 TN1148 1 
2 1 S52689 0 
3 2 TA2081 1 
4 2 TA2592 1 
5 2 TA4011 0 
6 2 TA4246 0 
7 2 TA4275 0 
8 2 TB0159 0 
9 2 TB0392 0 
10 3 TB0454 1 
11 3 TB0496 1 
12 3 TB1181 1 
13 3 TC0027 0 
14 3 TC1340 0 
15 3 TC2247 0 
16 3 TC3094 0 
17 3 TD0106 0 
18 3 TD1146 0 
19 3 TD1796 0 
20 3 TD3587 0 

Output 

1 1 TN1148 1 
2 1 S52689 0 
3 2 TA2081 1 
4 2 TA2592 1 
5 2 TA4011 0 
6 2 TA4246 0 
7 2 TA4275 0 
8 2 TB0159 0 
10 3 TB0454 1 
11 3 TB0496 1 
12 3 TB1181 1 
13 3 TC0027 0 
14 3 TC1340 0 
15 3 TC2247 0 
16 3 TC3094 0 
17 3 TD0106 0 
18 3 TD1146 0 
+0

Vous devez reformuler la question car je ne comprends pas très bien ce que vous appelez les groupes et ce que vous appelez les champs. Dans awk, les champs ont une signification très spécifique qui complique davantage le problème comme indiqué. – SiegeX

+0

J'ai édité votre question de sorte que le format d'entrée/sortie soit lisible maintenant. Pour un nouvel avis, mettez en surbrillance votre code et appuyez sur CTRL + K ou cliquez sur l'icône '101' dans l'éditeur. – SiegeX

+0

Le champ 2 a 3 "groupes" 1, 2 et 3. Espérons que cela clarifie. Merci SiegeX. – Tony

Répondre

0
#!/usr/bin/awk -f 
# by Dennis Williamson - 2010-12-02 
# for http://stackoverflow.com/questions/4334167/selecting-first-nth-rows-by-groups-using-awk 
$2 == prev { 
    count += $4 
    groupcount++ 
    array[idx++] = $0 
} 
$2 != prev { 
    if (NR > 1) { 
     for (i=0; i<count*3; i++) { 
      if (i == groupcount) break 
      print array[i] 
     } 
    } 
    prev = $2 
    count = 1 
    groupcount = 1 
    split("", array) # delete the array 
    idx = 0 
    array[idx++] = $0 
} 
END { 
    for (i=0; i<count*3; i++) { 
     if (i == groupcount) break 
     print array[i] 
    } 
} 
+0

Cher Dennis - Un grand merci pour vos efforts. Je viens de tester le programme, mais il n'a pas produit la sortie attendue. La sortie a 37 lignes et les lignes sont hors service. Toute modification possible? À votre santé. Tony – Tony

+0

@Tony: À l'aide des données d'échantillon fournies, sa sortie est exactement la même que celle de l'échantillon. Obtenez-vous les résultats corrects à partir des données d'échantillon? Pouvez-vous être plus précis sur la façon dont cela ne fonctionne pas? –

+0

Dennis- d'abord, je me suis 37 rangées et les premières lignes, I obtenu ARE1 1 TN1148 1 2 1 S52689 0 3 2 1 TA2081 1 1 1 TN1148 2 1 0 S52689 ... – Tony

2

La clé de ce programme awk est de transmettre le fichier d'entrée deux fois: une fois pour compter le nombre de lignes que vous voulez et une fois pour les imprimer.

awk ' 
    NR == FNR {wanted_rows[$2] += 3*$4; next} 
    --wanted_rows[$2] >= 0 {print} 
' input_file.txt input_file.txt 
+0

Cher Glenn- Wow, je viens de tester votre programme, ça fonctionne bien. J'ai un fichier beaucoup plus grand pour tester environ 1,8 million de lignes et je vous tiendrai au courant. - Merci beaucoup - BTW, C'est la première fois que je trouve le même fichier d'entrée est passé deux fois. Je n'ai jamais pensé à cette idée – Tony

+0

Les deux réponses sont valides. Ils montrent tous deux leur élégance à part entière. – Tony