2017-10-18 7 views
2

Comment faire correspondre l'année de manière générale aux exemples suivants.Regex: extraction de nombres à partir de parenthèses avec plusieurs correspondances

a <- '"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}' 
b <- 'Þegar það gerist (1998/I) (TV)' 

J'ai essayé ce qui suit, mais je n'ai pas eu le plus grand succès.

gsub('.+\\(([0-9]+.+\\)).?$', '\\1', a) 

Ce que je pensais que ce fait était d'aller jusqu'à ce qu'il trouve un (, il serait alors faire un groupe de numéros, puis tout caractère jusqu'à ce qu'il rencontre un). Et s'il y a plusieurs matches, je veux extraire le premier groupe.

Des suggestions à l'endroit où je me trompe? Je l'ai fait dans R.

+0

Donc, les correspondances attendues sont '1953' et' 1998'? Essayez 'sub (" ^. *? \\ ((\\ d {4}) [^)] * \\). * "," \\ 1 ", a)' –

+0

Oui, désolé de ne pas le signaler . –

Répondre

1

Votre motif contient .+ parties qui correspondent à un ou plusieurs caractères autant que possible, et au mieux votre motif pourrait saisir les 4 derniers morceaux des chaînes entrantes.

Vous pouvez utiliser

^.*?\((\d{4})(?:/[^)]*)?\).* 

Remplacer par \1 pour ne garder que le numéro à 4 chiffres. Voir the regex demo.

Détails

  • ^ - début de la chaîne
  • .*? - tout 0+ caractères aussi peu que possible
  • \( - un (
  • (\d{4}) - Groupe 1: quatre chiffres
  • (?: - début d'un non-c optionnel groupe apturing
    • / - un /
    • [^)]* - tout 0+ caractères autres que )
  • )? - fin du groupe
  • \) - un ) (en option, peut être omise)
  • .* - le reste de la chaîne.

Voir la R demo:

a <- c('"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}', 'Þegar það gerist (1998/I) (TV)', 'Johannes Passion, BWV. 245 (1725 Version) (1996) (V)') 
sub("^.*?\\((\\d{4})(?:/[^)]*)?\\).*", "\\1", a) 
# => [1] "1953" "1998" "1996" 

Une autre solution de base de R est de faire correspondre les 4 chiffres après (:

regmatches(a, regexpr("\\(\\K\\d{4}(?=(?:/[^)]*)?\\))", a, perl=TRUE)) 
# => [1] "1953" "1998" "1996" 

Le motif \(\K\d{4} correspond ( et tombe ensuite en raison de \K match de réinitialiser l'opérateur, puis (?=(?:/[^)]*)?\\)) lookahead s'assure qu'il y a un optionnel / + 0+ ch ars autre que ) puis ). Notez que regexpr extrait uniquement la première correspondance.

+0

Merci, ça fait l'affaire. Je vais vérifier la réponse dans 5 minutes si disponible. –

+0

Y at-il un moyen de capturer l'année correcte dans 'Johannes Passion, BWV. 245 (Version de 1725) (1996) (V) 'aussi? Ici, il capture le "1725" plutôt que 1996. –

+0

Vous devriez être plus précis sur le modèle alors. * a (, alors cela ferait un groupe de nombres, puis n'importe quel caractère jusqu'à ce qu'il rencontre a) * ne couvre pas celui-ci. –

2

Vous pouvez utiliser

library(stringr) 

strings <- c('"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}', 'Þegar það gerist (1998/I) (TV)') 

years <- str_match(strings, "\\((\\d+(?: B\\.C\\.)?)")[,2] 
years 
# [1] "1953" "1998" 

L'expression est ici

\(    # (
(\d+    # capture 1+ digits 
    (?: B\.C\.)? # B.C. eventually 
) 

Notez que antislashs doivent être échappé à R.

+0

Si vous voulez définir les époques, il peut être plus logique d'ajouter une alternative 'A.D. –

+0

@ WiktorStribiżew: Comme vu dans les commentaires à votre question, il pourrait ne pas encore être clair ce que OP veut vraiment, alors je le laisse tel quel. – Jan