2015-12-10 1 views
1

J'ai un input.txt de fichier avec le contenu suivant:Bash regexp * correspond trop loin

foo 
[assembly: AssemblyVersion("1.2.3")] 
bar")] 
quux 

Pour correspondre à la 1.2.3 de l'entrée le script suivant est utilisé:

#!/bin/bash 
regex='\[assembly: AssemblyVersion\("(.*)"\)\]' 
fileContent=$(cat input.txt) 
[[ "$fileContent" =~ $regex ]] 
echo "${BASH_REMATCH[1]}" 

I on peut attendre que la sortie soit 1.2.3 mais il est:

1.2.3")] 
bar 

Pourquoi est-ce ainsi? Comment le réparer?

Le testeur d'expressions régulières au https://regex101.com fonctionne comme prévu.

+1

Avidité. Essayez ''\ [assembly: AssemblyVersion \ (" ([^()] *) "\) \]''. –

+0

@stribizhev Wow, sympa, fonctionne en effet. Merci beaucoup! – alvarez

Répondre

4

Le .* est appelé un sous-motif correspondant de points avide et il correspond " et ), tout caractère including a newline.

Ainsi, la meilleure astuce pour limiter la greediness utilise une classe de caractères niée [^"] qui correspond à tout caractère mais " (s'il n'y a pas de guillemets à l'intérieur de la chaîne entre guillemets):

'\[assembly: AssemblyVersion\("([^"]*)"\)\]' 
           ^^^^^ 

Demo

ou - s'il ne devrait pas ( et ) dans la chaîne entre guillemets:

'\[assembly: AssemblyVersion\("([^()]*)"\)\]' 
           ^^^^^ 

Demo

+0

En fait, les deux solutions supposent ici qu'il n'y a que des espaces, des signes de ponctuation de base et des caractères de mots à l'intérieur de la chaîne entre guillemets. S'il peut y avoir des entités échappées, la regex sera un peu plus compliquée: [''\ [assembly: AssemblyVersion \ (" ([^ \\ "] * (\\. [^ \\"] *) *) " \) \] ''] (http://ideone.com/luGBKQ). –

+0

En fait, le '.' * * correspond à un retour à la ligne; c'est ainsi que la gourmandise du '*' cause un problème. – chepner

+0

@chepner: C'est vrai, j'ai tapé ça automatiquement sans réfléchir. [* Dans les cas où il y a un saut de ligne dans une expression à plusieurs lignes, le point correspond à la nouvelle ligne. *] (Http://tldp.org/LDP/abs/html/x17129.html#FTN.AEN17189) –