Vérifier le numéro dans un autre fichier s’il est dans la plage à l’aide du script shell

J’ai deux fichiers (fileA et fileB). FileA contient la liste des numéros et fileB contient la plage de numéros.

déposer un

446646452 000000001 63495980020 

fileB (range_from et range_to)

  22400208, 22400208 446646450, 446646450 63495980000, 63495989999 

La sortie doit être

  63495980020 

Dans le script SQL, c’est juste comme

  select * from fileB where 446646452 between Range_from and Range_To 

Comment puis-je le faire en utilisant un script shell?

Pour des raisons de clarification, chaque valeur de fileA doit être vérifiée par rapport à toutes les plages de fileB pour voir si elle se situe dans au moins une plage.
>= et <= logique de la vérification de la plage est supposée (c.-à-d. que les valeurs qui coïncident avec les points limites de la plage sont incluses).

 awk -F', +' ' # 1st pass (fileB): read the lower and upper range bounds FNR==NR { lbs[++count] = $1+0; ubs[count] = $2+0; next } # 2nd pass (fileA): check each line against all ranges. { for(i=1;i<=count;++i) { if ($1+0 >= lbs[i] && $1+0 <= ubs[i]) { print; next } } } ' fileB fileA 
  • awk est utilisé pour lire les deux fichiers, en utilisant des passes distinctes:
    • FNR==NR est vrai pour toutes les lignes de fileB ; des tableaux parallèles pour les limites inférieures ( lbs ) et les limites supérieures ( ubs ) des plages sont construits; Grâce à next , aucun traitement supplémentaire n'est appliqué aux lignes fileB .
    • Le bloc suivant {...} n'est alors appliqué qu'aux lignes de fileA .
    • Chaque valeur de fileA est vérifiée par rapport à toutes les plages et dès qu'une correspondance est trouvée, la ligne d'entrée est imprimée et le traitement passe à la ligne suivante.
    • Pour s'assurer que tous les jetons impliqués sont traités comme des nombres , +0 est ajouté.

Impression de numéros correspondant à n’importe laquelle des gammes

 $ awk 'FNR==NR{low[NR]=$1+0; hi[NR]=$2+0;next} {for (i in low)if ($1>low[i] && $1 

Comment ça marche

  • FNR==NR{low[NR]=$1+0; hi[NR]=$2+0;next}

    Lors de la lecture du premier fichier, fileB , enregistrez le bas de la plage dans le tableau low et le haut dans le tableau hi .

  • for (i in low)if ($1>low[i] && $1

    Lors de la lecture du deuxième fichier, fileA , vérifiez le nombre par rapport à chaque plage. S'il satisfait à l'une des plages, imprimez-le et passez à la ligne next .

Impression de nombres correspondant à leur plage respective

 $ paste fileA fileB | awk '$1>$2+0 && $1<$3+0{print $1}' 63495980020 

Notez que seul le 63495980020 est imprimé. 446646452 n'est pas compris entre 22400208 et 22400208, il est donc omis.

Comment ça marche

La paste utilitaire combine les fichiers comme ceci:

 $ paste fileA fileB 446646452 22400208, 22400208 000000001 446646450, 446646450 63495980020 63495980000, 63495989999 

La première colonne est le nombre qui nous intéresse, tandis que la seconde est la valeur basse de la plage et la troisième la valeur la plus élevée. Nous voulons imprimer la première valeur, $1 , si elle se situe entre le deuxième et le troisième. Pour tester s'il est plus grand que le second, nous pouvons essayer:

 $1>$2 

Cependant, pour s'assurer que awk traite les champs sous forme de nombres, pas de chaînes, nous effectuons une addition sur l'un des nombres comme ceci:

 $1>$2+0 

De même, pour tester si le premier nombre est inférieur au troisième:

 $1<$3+0 

En mettant ces deux tests avec une commande d’impression, vous obtenez:

 $1>$2+0 && $1<$3+0 {print $1} 

Ce test fait ssortingctement entre . Selon vos besoins, vous préférerez peut-être:

 $1>=$2+0 && $1<=$3+0 {print $1} 

Ancien script de mode

 sed 's/,[[:space:]]*/ /' fileB \ | while read LowVal HighVal do while read ThisLine do [ ${ThisLine} -ge ${LowVal} ] && [ ${ThisLine} -le ${HighVal} ] && echo "${ThisLine}" done < fileA done