2 votes

Recherche d'une expression régulière dans un fichier correspondant à une valeur donnée

J'ai quelques connaissances de base sur l'utilisation des expressions régulières avec grep (bash). Mais je veux utiliser les expressions régulières dans l'autre sens.

Par exemple, j'ai un fichier contenant les entrées suivantes :

line_one=[0-3]
line_two=[4-6]
line_three=[7-9]

Maintenant, je veux utiliser bash pour savoir à quelle ligne correspond un nombre particulier. Par exemple :

grep 8 file

devrait revenir :

line_three=[7-9]

Remarque : je suis conscient que l'exemple de "grep 8 file" n'a pas de sens, mais j'espère qu'il aidera à comprendre ce que j'essaie de faire.

Merci pour votre aide, Marcel

3voto

yankee2905 Points 1077

Comme d'autres l'ont souligné, awk est l'outil idéal pour cela :

awk -F'=' '8~$2{print $0;}' file

... et si vous voulez que cet outil ressemble plus à grep, une enveloppe rapide en bash :

#!/bin/bash
awk -F'=' -v seek_value="$1" 'seek_value~$2{print $0;}' "$2"

Ce qui donnerait :

./not_exactly_grep.sh 8 file
line_three=[7-9]

2voto

Charles Duffy Points 34134

Cela peut être fait en bash natif en utilisant la syntaxe [[ $value =~ $regex ]] à tester :

find_regex_matching() {
  local value=$1
  while IFS= read -r line; do         # read from input line-by-line
    [[ $line = *=* ]] || continue     # skip lines not containing an =
    regex=${line#*=}                  # prune everything before the = for the regex
    if [[ $value =~ $regex ]]; then   # test whether we match...
      printf '%s\n' "$line"           # ...and print if we do.
    fi
  done
}

...utilisé comme :

find_regex_matching 8 <file

...ou, pour le tester avec votre exemple d'entrée en ligne :

find_regex_matching 8 <<'EOF'
line_one=[0-3]
line_two=[4-6]
line_three=[7-9]
EOF

...qui émet correctement :

line_three=[7-9]

Vous pourriez remplacer printf '%s\n' "$line" con printf '%s\n' "${line%%=*}" pour imprimer uniquement la clé (contenu avant le = ), si vous le souhaitez. Voir la page des bash-hackers sur l'expansion des paramètres pour un aperçu de la syntaxe utilisée.

1voto

meta11co Points 11

Ma première impression est que ce n'est pas une tâche pour grep, peut-être pour awk.

En essayant de faire des choses avec grep, je ne vois que ceci :

for line in $(cat file); do echo 8 | grep "${line#*=}" && echo "${line%=*}" ; done

Utilisation de while pour la lecture de fichiers (après les commentaires) :

while IFS= read -r line; do echo 8 | grep "${line#*=}" && echo "${line%=*}" ; done < file

0voto

Ce n'est pas une fonctionnalité intégrée de grep mais c'est facile à faire avec awk avec un changement de syntaxe :

/[0-3]/ { print "line one" }
/[4-6]/ { print "line two" }
/[7-9]/ { print "line three" }

Si vous en avez vraiment besoin, vous pouvez changer votre fichier d'entrée de façon programmatique pour utiliser cette syntaxe, s'il ne contient pas de caractères qui nécessitent un échappement (principalement / dans l'expression rationnelle ou " dans la chaîne) :

sed -e 's@\(.*\)=\(.*\)@/\2/ { print "\1" }@'

0voto

dawg Points 26051

Si je comprends bien, vous cherchez une fourchette qui inclut une certaine valeur.

Vous pouvez le faire dans gawk :

$ cat /tmp/file
line_one=[0-3]
line_two=[4-6]
line_three=[7-9]

$ awk  -v n=8 'match($0, /([0-9]+)-([0-9]+)/, a){ if (a[1]<n && a[2]>n) print $0 }' /tmp/file
line_three=[7-9]

Puisque les chiffres sont traités comme des nombres (au lieu d'une regex), il est possible d'utiliser des plages plus larges :

$ cat /tmp/file
line_one=[0-3]
line_two=[4-6]
line_three=[75-95]
line_four=[55-105]

$ awk  -v n=92 'match($0, /([0-9]+)-([0-9]+)/, a){ if (a[1]<n && a[2]>n) print $0 }' /tmp/file
line_three=[75-95]
line_four=[55-105]

Si vous cherchez simplement à interpréter le côté droit de l'écran de l = comme un regex, vous pouvez faire :

$ awk  -F= -v tgt=8 'tgt~$2' /tmp/file

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X