1
votes

AWK: 2 colonnes 2 fichiers s'affichent là où la deuxième colonne contient des données uniques

J'ai besoin de la première colonne pour vérifier si elle ne correspond pas à la première colonne du deuxième fichier. Cependant, si la deuxième colonne correspond à la deuxième colonne du deuxième fichier, pour afficher ces données avec awk sous Linux.

Je veux que awk détecte le changement avec la première et la deuxième colonne du premier fichier avec le deuxième fichier.

file1.txt
sdsdjs ./file.txt
sdsksp ./example.txt
jsdjsk ./number.txt
dfkdfk ./ok.txt

file2.txt
sdsdks ./file.txt <-- different
sdsksd ./example.txt   <-- different
jsdjsk ./number.txt <-- same
dfkdfa ./ok.txt <-- different

Expected output:
sdsdks ./file.txt
sdsksd ./example.txt
dfkdfa ./ok.txt

Remarquez comment dans le deuxième fichier il peut y avoir des lignes manquantes et pas les mêmes que le premier.

Comme vu ci-dessus, comment awk peut-il afficher les résultats uniquement là où la deuxième colonne est unique et ne correspond pas à la première colonne?

awk

1 commentaires

Pourriez-vous préciser ce que vous entendez par: Remarquez comment, dans le deuxième fichier, il peut y avoir des lignes manquantes et différentes du premier. car les deux fichiers contiennent exactement le même nombre de lignes.


6 Réponses :


3
votes

Quelque chose comme ceci pourrait fonctionner pour vous:

awk 'FNR == NR { f[FNR"_"$1] = 1; next }
     !f[FNR"_"$1]' file1.txt file2.txt

Répartition:

FNR == NR {                        } # Run on first file as FNR is record number for the file, while NR is the global record number
            f[FNR"_"$2] = $1;        # Store first column under the name of  FNR followed by an underbar followed by the second column 
                              next   # read next record and redo
f[FNR"_"$2] && f[FNR"_"$2] != $1     # If the first column doesn't match while the second does, then print the line

Une approche plus simple qui ignorera la deuxième colonne est:

awk 'FNR == NR { f[FNR"_"$2] = $1; next }
     f[FNR"_"$2] && f[FNR"_"$2] != $1' file1.txt file2.txt


1 commentaires

@Dave supprime simplement le {print $ 2} des solutions.



2
votes

Si les enregistrements ne doivent pas être dans la position respective dans les fichiers, c.-à-d. nous comparons les chaînes de deuxième colonne correspondantes, cela devrait suffire:

$ awk '{if($2 in a){if($1!=a[$2])print $1,$2}else a[$2]=$1}'  file1 file2
sdsdks ./file.txt
sdsksd ./example.txt
dfkdfa ./ok.txt

Sortie:

$ awk '{
    if($2 in a) {           # if $2 match processing
        if($1!=a[$2])       # and $1 don t
            print $2        # output
    } else                  # else
        a[$2]=$1            # store
}' file1 file2

En jolis caractères:

file.txt

Mise à jour :

$ awk '{if($2 in a){if($1!=a[$2])print $2}else a[$2]=$1}' file1 file2

En gros, a changé le print $ 2 en print 1 $, 2 $ .


1 commentaires

La première et la deuxième colonne sont utilisées conjointement pour comparer le contenu du fichier précédent ...



0
votes

La façon dont votre question est formulée est très déroutante, mais après l'avoir lue plusieurs fois et en regardant votre sortie attendue publiée, JE PENSE que vous essayez juste de dire que vous voulez les lignes de fichier2 qui n'apparaissent pas dans fichier1. Si c'est le cas, c'est juste:

$ awk 'NR==FNR{a[$1,$2];next} !(($1,$2) in a)' file1 file2
sdsdks ./file.txt
sdsksd ./example.txt
dfkdfa ./ok.txt

Si vos données réelles ont plus de champs que ce qui est indiqué dans votre exemple d'entrée mais que vous ne voulez que les 2 premiers champs pris en compte pour la comparaison, corrigez votre question pour afficher un plus vrai exemple représentatif, mais la solution serait:

$ awk 'NR==FNR{a[$0];next} !($0 in a)' file1 file2
sdsdks ./file.txt
sdsksd ./example.txt
dfkdfa ./ok.txt

si ce n'est pas le cas, veuillez modifier votre question pour clarifier ce que vous essayez de faire et inclure un exemple où ce qui précède ne produit pas le résultat attendu.


0 commentaires

0
votes

Je comprends le problème d'origine de la manière suivante:

  • Deux fichiers, fichier1 et fichier2 contiennent un ensemble de paires valeur-clé .
  • La clé est le nom du fichier, la valeur est la chaîne dans la première colonne
  • Si une clé correspondante est trouvée entre fichier1 et fichier2 mais que la valeur est différente, imprimez la correspondance ligne de file2

Vous n'avez pas vraiment besoin de awk avancé pour cette tâche, cela peut facilement être réalisé avec un simple pipeline de awk et grep.

$ awk '{print $NF}' file2.txt | grep -wFf - file1.txt | grep -vwFf - file2.txt
sdsdks ./file.txt
sdsksd ./example.txt
dfkdfa ./ok.txt

Ici, le grep sélectionnera d'abord les lignes de file1.txt qui ont la même clé (nom de fichier). Le second grep essaiera de rechercher toutes les lignes correspondantes à partir de fichier1 dans fichier2, mais il imprimera les échecs. Sachez que dans ce cas, les lignes doivent être complètement identiques.

Si vous souhaitez simplement utiliser awk, alors la logique ci-dessus est réalisée avec la solution présentée par Ed Morton . Inutile de le répéter ici.


0 commentaires

0
votes

Je pense que c'est ce que vous recherchez

$ awk 'NR==FNR{a[$2]=$1; next} a[$2]!=$1' file1 file2

sdsdks ./file.txt
sdsksd ./example.txt  
dfkdfa ./ok.txt

imprimez les enregistrements du fichier2 où les valeurs de champ1 sont différentes pour la même valeur de champ2. Ce script suppose que les valeurs de champ2 sont uniques dans chaque fichier, afin qu'il puisse être utilisé comme clés. Étant donné que le contenu ressemble à des chemins de fichiers, il s'agit d'une hypothèse valable. Sinon, vous devez peut-être faire correspondre les enregistrements avec les numéros de ligne correspondants.


0 commentaires

0
votes

Dans le cas où vous recherchez un diff basé sur des lignes plus simple basé sur le premier champ d'une ligne étant différent.

awk 'NR==FNR { a[NR] = $1; next } a[FNR]!=$1' file1 file2


0 commentaires