2013-08-24 9 views
7

Mam treść tekstu Szukam wyciągnąć zestawy powtórzeń 4-cyfrowych numerów z.Regex: Dopasowywanie 4-cyfrowych w słowach

na przykład:

Pierwszy to 1234 2) Drugi to 2098 3) trzeci jest 3213

Teraz wiem, że jestem w stanie uzyskać pierwszego zbioru cyfr out używając zwyczajnie:

/\d{4}/ 

... wracając 1234

ale jak mam pasuje do drugiego zestawu cyfr lub trzeciego itd.?

edit: Jak mogę powrócić 2098 lub 3213

+7

W jakim języku się posługujesz? –

+1

Witaj, Rohit. Używam Perla. Mój błąd, założyłem, że Regex jest taki sam. –

+2

A dla rekordu istnieje kilka "dialektów" wyrażeń regularnych, każdy z własnym zestawem obsługiwanych funkcji. Na przykład, RegExp w JavaScript nie obsługuje negatywnych look-behinds, które są obsługiwane przez regexps w stylu Perla. –

Odpowiedz

1

Zobacz http://perldoc.perl.org/perlre.html do dyskusji na temat korzystania z „G” modyfikator, który spowoduje, że wyrażenie regularne, aby dopasować wszystkie occurrances jego wzór, a nie tylko pierwszego.

+0

Używam systemu, który akceptuje tylko wyrażenie regularne jako część funkcji, zajmuje tylko pierwsze dopasowanie i nie pozwala mi używać modyfikatorów takich jak "g". Chciałbym szukać składni, która powiedziałaby "daj mi drugi mecz z \ d {4} \ .Nie wiem, czy mam sens. –

+2

Co dokumentacja funkcji, której używasz, mówi o dopasowywaniu wielu kopii wzoru? ... Jaka jest funkcja? –

0

Jeśli wyrażenie regularne dopasowane tylko raz, a następnie dopasować wszystkie trzy w jednym regex i wyodrębnić je za pomocą grup dopasowane:

^.*\b(\d{4})\b.*\b(\d{4})\b.*\b(\d{4})\b.*$ 

trzy numery 4-cyfrowe będą przechwytywane w grupie 1. 2 i 3.

+1

Myślę, że spowoduje to problemy z przykładem OP, ponieważ źródło zawiera "1)" i "2)", a to zakończy się niepowodzeniem testu '\ D +'. – ajb

+0

@ajb good point - masz rację.) A co powiesz na to teraz? – Bohemian

+1

Tak, to powinno być lepsze. '\ b' jest podejściem, które podchodzili inni i ja, ale jeśli OP chce wydobyć 1234 z ANumber1234InTheMiddleOfAWord to potrzebowalibyśmy czegoś innego Dokładnie nie znamy jego dokładnych wymagań – ajb

1

Jeśli chcesz wzór, który znajdzie grupę $n „th 4-cyfrowy, to wydaje się działać:

$pat = "^(?:.*?\\b(\\d{4})\\b){$n}"; 
if ($s =~ /$pat/) { 
    print "Found $1\n"; 
} else { 
    print "Not found\n"; 
} 

zrobiłem to poprzez budowanie wzór ciąg, bo nie mógł dostać va riable interpolowane do kwantyfikatora {$n}.

Ten wzór znajduje 4-cyfrowe grupy, które znajdują się na granicach słów (testy \b); Nie wiem, czy to spełnia twoje wymagania. Wzorzec używa .*?, aby zapewnić, że jak najmniej znaków jest dopasowanych do każdej czterocyfrowej grupy. Wzorzec jest dopasowywany $n razy, a grupa przechwytywania $1 jest ustawiona tak, jak w ostatniej iteracji, tj. $n 'th.

EDYCJA: Kiedy po raz kolejny wypróbowałem to, wydawało się interpolować $n w kwantyfikatorze. Nie wiem, co zrobiłem inaczej, niż ostatnio. Więc może to będzie działać:

if ($s =~ /^(?:.*?\b(\d{4}\b){$n}/) { ... 

Jeśli nie, patrz Amona komentarz o qr//.

+1

Ah, przerażający podwójny ukośnik lewy. Protip: Użyj wyrażeń regularnych 'qr //'. Następnie: 'qr/^ (?:. *? \ B (\ d {4}) \ b) {$ n}/x' – amon

11

Wygląda na to, że nie masz jeszcze odpowiedniej odpowiedzi na swoje pytanie.

Rozwiązaniem jest użycie modyfikatora /g w swoim regex.W kontekście listy znajdzie wszystkie numerów w swojej ciąg naraz, jak ten

my $str = 'The first is 1234 2) The Second is 2098 3) The Third is 3213'; 

my @numbers = $str =~ /\b \d{4} \b/gx; 

print "@numbers\n"; 

wyjściu

1234 2098 3213 

Albo można iterację nich, wykorzystując kontekst skalarny w while pętla, taka jak ta

while ($str =~ /\b (\d{4}) \b/gx) { 
    my $number = $1; 
    print $number, "\n"; 
} 

Wyjście

1234 
2098 
3213 

Dodałem \b wzorce do regex tak, że tylko mecze całych numerów czterocyfrowych a nie, na przykład, znaleźć 1234 w 1234567. Modyfikator /x pozwala mi dodawać spacje, dzięki czemu wzór jest bardziej zrozumiały.

0

Odpowiedź Ajba z "gx" jest najlepsza. Jeśli wiesz, że będziesz mieć trzy liczby, ta prosta linia rozwiąże ten problem:

my $str = 'The first is 1234 2) The Second is 2098 3) The Third is 3213'; 
my ($num1, $num2, $num3) = $str =~ /\b \d{4} \b/gx; 
print "$num1, $num2, $num3\n"; 
Powiązane problemy