web-dev-qa-db-fra.com

grep: capture de groupe

J'ai la chaîne suivante:

{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}

et je dois obtenir la valeur de "version du schéma", qui est 1234 dans cet exemple.

J'ai essayé

grep -Eo "\"scheme_version\":(\w*)"

mais ça revient

"scheme_version":1234

Comment puis-je le faire? Je sais que je peux ajouter sed call, mais je préférerais le faire avec un seul grep.

50
lstipakov

Cela pourrait fonctionner pour vous:

echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' |
sed -n 's/.*"scheme_version":\([^}]*\)}/\1/p'
1234

Désolé, ce n'est pas grep, alors ignorez cette solution si vous le souhaitez.

Ou coller avec grep et ajouter:

grep -Eo "\"scheme_version\":(\w*)"| cut -d: -f2
51
potong

Vous aurez besoin de regarder derrière l'assertion pour qu'elle ne soit pas incluse dans le match:

grep -Po '(?<=scheme_version":)[0-9]+'

61
SiegeX

Je vous recommande d'utiliser jq pour le travail. jq est un processeur JSON en ligne de commande.

$ cat tmp
{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}

$ cat tmp | jq .scheme_version
1234
37
Marc O'Morain

Au lieu de la méthode de recherche positive suggérée par SiegeX, vous pouvez réinitialiser le point de départ de la correspondance directement après scheme_version": avec le \K séquence d'échappement. Par exemple.,

$ grep -Po 'scheme_version":\K[0-9]+'

Ceci redémarre le processus de correspondance après avoir apparié scheme_version":, et a tendance à avoir des performances bien meilleures que le lookbehind positif. La comparaison des deux sur regexp101 montre que la méthode de démarrage du match de réinitialisation prend 37 étapes et 1 ms, tandis que la méthode de recherche positive prend 194 étapes et 21 ms.

Vous pouvez comparer la performance vous-même sur regex101 et en savoir plus sur la réinitialisation du point de départ de la correspondance dans documentation PCRE .

23
ClarkZinzow

Pour éviter d'utiliser greps la fonctionnalité PCRE disponible dans GNU grep , mais pas dans version BSD , une autre méthode consiste à utiliser - ripgrep , par exemple.

$ rg -o 'scheme_version.?:(\d+)' -r '$1' <file.json 
1234

-rIndex de groupe de capture (par exemple, $5) et des noms (par exemple, $foo).

Un autre exemple avec Python et json.tool module qui peut valider et imprimer en joli:

$ python -mjson.tool file.json | rg -o 'scheme_version[^\d]+(\d+)' -r '$1'
1234

Connexes: grep peut-il afficher uniquement les groupes qui correspondent?

5
kenorb

Tu peux le faire:

$ echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' | awk -F ':' '{print $4}' | tr -d '}'
2
kris.zhang