J'utilise Solaris 10 et les options grep impliquant -f ne fonctionnent donc pas.
J'ai deux fichiers séparés par des tuyaux:
fichier1:
abc|123|BNY|apple|
cab|234|cyx|orange|
def|kumar|pki|bird|
fichier 2:
abc|123|
kumar|pki|
cab|234
Je voudrais comparer les deux premières colonnes de file2 avec file1 (rechercher dans tout le contenu de file1 dans les deux premières colonnes) si elles correspondent imprimer la ligne correspondante de file1. Recherchez ensuite la deuxième ligne du fichier 2 et ainsi de suite.
Production attendue:
abc|123|BNY|apple|
cab|234|cyx|orange|
Les fichiers que j'ai sont énormes, contenant environ 400 000 lignes, donc je voudrais rendre l'exécution rapide.
shell-script
text-processing
perl
user68365
la source
la source
grep
, c'est sous/usr/sfw/bin/ggrep
. stackoverflow.com/questions/15259882/…Réponses:
C'est pour cela que awk a été conçu:
Explication
-F'|'
: définit le séparateur de champ sur|
.NR==FNR
: NR est le numéro de ligne d'entrée actuel et FNR le numéro de ligne du fichier actuel. Les deux ne seront égaux que pendant la lecture du 1er fichier.c[$1$2]++; next
: s'il s'agit du 1er fichier, enregistrez les deux premiers champs duc
tableau. Ensuite, passez à la ligne suivante pour que cela ne soit appliqué que sur le 1er fichier.c[$1$2]>0
: le bloc else ne sera exécuté que s'il s'agit du deuxième fichier donc nous vérifions si les champs 1 et 2 de ce fichier ont déjà été vus (c[$1$2]>0
) et s'ils l'ont été, nous imprimons la ligne. Dansawk
, l'action par défaut consiste à imprimer la ligne. Sic[$1$2]>0
c'est vrai, la ligne sera imprimée.Alternativement, puisque vous avez tagué avec Perl:
Explication
La première ligne s'ouvrira
file2
, lira tout jusqu'au 2ème|
(.+?\|[^|]+
) et l'enregistrera ($&
le résultat du dernier opérateur de correspondance) dans le%k
hachage.La deuxième ligne traite file1, utilise la même expression régulière pour extraire les deux premières colonnes et imprimer la ligne si ces colonnes sont définies dans le
%k
hachage.Les deux approches ci-dessus devront conserver les 2 premières colonnes du fichier 2 en mémoire. Cela ne devrait pas être un problème si vous n'avez que quelques centaines de milliers de lignes, mais si c'est le cas, vous pourriez faire quelque chose comme
Mais ce sera plus lent.
la source
file2
mémoire?awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0'
est une version plus courte.file2
-il des lignes en double?je pense
est ce que vous recherchez. Il devrait être efficace, mais je ne suis pas sûr qu'il sera aussi précis que vous le souhaitez. Si
abc|123
(par exemple) se trouve dans une lignefile1
dans des colonnes différentes, cette ligne sera également imprimée. Si vous pouvez garantir que cela ne se produira jamais, la ligne ci-dessus devrait fonctionner.la source
Si vous souhaitez penser le problème de manière similaire à SQL, alors vous devriez certainement essayer un outil nommé ' q ':
Il est plus clair et plus facile à comprendre si vous connaissez la requête SQL.
la source
la source