1
votes

AWK recherche des enregistrements dans un fichier pour des entrées dans un autre fichier

J'ai un fichier results.csv qui contient des noms dans la mise en page suivante:

record_seperator
name2
bla
bluh

et un sample.txt, qui est structuré comme suit

record_seperator
name1
foo
bar


0 commentaires

4 Réponses :


1
votes

En voici une. Comme il n'y avait pas de sortie attendue, il ne produit que des enregistrements bruts :

$ cat name1.txt
record_seperator
name1
foo
bar

Une seule correspondance:

$ awk '
NR==FNR {              # process first file 
    a[$1]=RS $0        # hash the whole record with first field (name) as key 
    next               # process next record in the first file
}                      # after this line second file processing
$1 in a {              # if first field value (name) is found in hash a
    f=$1 ".txt"        # generate filename
    print a[$1] > f    # output the whole record
    close(f)           # preserving fds
}' RS="record_seperator\n" sample RS="\n" FS="," results  # file order and related vars

Testé sur gawk et mawk, agit bizarrement sur original-awk.


3 commentaires

Merci pour la réponse rapide. Je dois admettre que je ne le comprends pas entièrement. J'ai ajouté la sortie attendue dans mon message d'origine.


le résultat doit contenir la ligne RS "record_seperator"


Merci beaucoup pour vos réponses! Désolé de rentrer si tard. J'ai eu la grippe et puis une tonne de travail s'est accumulée.



0
votes

quelque chose comme ça, ( non testé )

$ awk -F, 'NR==FNR {a[$1]; next}                  # fill array with names from first file
           $1 in a {print rt, $0 > ($1".txt")}    # print the record from second file
                   {rt = RT}' results.csv RS="define_it_here" sample.txt  

puisque votre séparateur d'enregistrements est avant les enregistrements, vous devez le retarder de un.

Utilisez l'itérateur de construction en ligne / enregistrement au lieu de le contourner.


0 commentaires

0
votes

(En suivant l'exemple de @ Tiw, j'ai également changé name5 en name2 dans votre fichier de résultats afin d'obtenir le résultat attendu)

$ cat name1.txt
record_seperator
name1
foo
bar
$ cat name2.txt
record_seperator
name2
bla
bluh

Exécutez avec gawk pour RS multi-caractères: p >

$ gawk -f a.awk FS="," results.csv FS="\n" RS="record_seperator\n" sample.txt

Résultats de la vérification:

$ cat a.awk
# collect the result names into an array
NR == FNR {a[$1]; next}

# skip the first (empty) sample record caused by initial record separator
FNR ==  1 { next }

# If found, output sample record into the appropriate file
$1 in a {
    f =  ($1 ".txt")
    printf "record_seperator\n%s", $0  > f
}


0 commentaires

0
votes

Vous codez les erreurs:

record_seperator 
name1            
foo              
bar              

record_seperator 
name2            
bla              
bluh             

Aussi l'exemple que vous avez montré:

#!/bin/bash
awk 'BEGIN{
    while ( (getline line< "results.csv") > 0 ) {  # Avoid infinite loop when read erorr encountered.
        split(line,name,",");
        nameArr[name[1]]; # Actually no need do anything, just refer once to establish the key (name[1]).
    }
    RS="record_seperator";
    FS="\n";
}

$2 in nameArr {
        print RS $0;  #You can add `> $2 ".txt"` later yourself.
}' sample.txt

Changement de name5 en nom2 , et avec votre propre code mis à jour:

name1, 2(random number)  
name5, 3  ## <-- name5 here, not name2 !

Sortie:

#!/bin/bash
awk 'BEGIN{
while (getline < "results.csv")
{
split($0,name,",");
nameArr[k]=name[1];  ## <-- k not exists, you are rewriting nameArr[""] again and again.
}
{
RS="record_seperator"
FS="\n"
for (key in nameArr) ## <-- only one key "" exists, it's never gonna equal to $2
        {
         print nameArr[key]  
         print $2
         if ($2==nameArr[key])
                 NR > 1
                 {
                #extract file by Record separator and name from line2
                print RS $0 > $2 ".txt"
                }
        }
}
}' sample.txt


0 commentaires