Wyrażenia regularne i wyszukiwanie podciągu

0

Witam,

Potrzebuje kodu który będzie wyszukiwał w tekście podciąg samych cyfr, najpierw 15, potem 10 jeśli nie znajdzie podciągu o długości 15 cyfr.

Chciałbym żeby ignorował spacje ale nie znaki alfabetyczne, czyli jeśli mam napis "12 qwerty 999 999 999 999 999przyklad"
to żeby skleił wszystkie "9". Obecnie mój kod zachowuje sie tak że dla tego badania wziąłby "129999999999999" czyli pominął by qwerty i nie doszedł nawet do ostatnich dwóch "9". Jak mogę to poprawić?
Mój kod:

                $afterCut = "8664saad--031031502sadad560IMEI866431031502560 Reklamacja naprawy"; //przykład

                $toCut = explode(' ',$number);
                $afterCut = implode('',$toCut);

                if(preg_match('/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/',$afterCut,$IMEImatches) == true)
                {
                        print_r($IMEImatches);
                        echo $cos =strlen($IMEImatches);
                }
                elseif(preg_match('/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/',$afterCut,$NrRepairMatches) == true)
                {
                        print_r( $NrRepairMatches);
                }

1

To nie jest może odpowiedź wprost na Twoje pytanie (i pewnie liczyłeś na coś innego), ale skoro nie ogarniasz regexów (to żaden zarzut, po prostu stwierdzenie faktu. Ja zresztą też ich nie lubię i używam jak już naprawdę muszę), to może pomyśl o jakiejś alternatywie. Zawsze można metodą jaskiniowców - rozbić string na poszczególne znaki, a potem za pomocą is_numeric (https://www.php.net/manual/en/function.is-numeric.php) sprawdzać, czy dany znak jest cyfrą. Potem sobie ciąg powstały z wyboru cyfr odpowiednio przetworzysz i po temacie.

Opcja numer 2 - ktoś poda Ci gotowe rozwiązanie, wpiszesz je na sztywno i pewnie będzie działać. Ale, ponieważ nie będziesz rozumieć jak to działa, za chwilę jak pojawi się potrzeba poprawienia czegoś, to problem do Ciebie wróci. A nie sądzę, żebyś teraz robił przyspieszony kurs regexów z powodu potrzeby wyciągnięcia jednego kodu ze stringa.

0
cerrato napisał(a):

To nie jest może odpowiedź wprost na Twoje pytanie (i pewnie liczyłeś na coś innego), ale skoro nie ogarniasz regexów (to żaden zarzut, po prostu stwierdzenie faktu. Ja zresztą też ich nie lubię i używam jak już naprawdę muszę), to może pomyśl o jakiejś alternatywie. Zawsze można metodą jaskiniowców - rozbić string na poszczególne znaki, a potem za pomocą is_numeric (https://www.php.net/manual/en/function.is-numeric.php) sprawdzać, czy dany znak jest cyfrą. Potem sobie ciąg powstały z wyboru cyfr odpowiednio przetworzysz i po temacie.

Opcja numer 2 - ktoś poda Ci gotowe rozwiązanie, wpiszesz je na sztywno i pewnie będzie działać. Ale, ponieważ nie będziesz rozumieć jak to działa, za chwilę jak pojawi się potrzeba poprawienia czegoś, to problem do Ciebie wróci. A nie sądzę, żebyś teraz robił przyspieszony kurs regexów z powodu potrzeby wyciągnięcia jednego kodu ze stringa.

No pewnie się nie wyrobie z kursem ale chciałbym to zrozumieć a nie jedynie kopiuj wklej.

0

chciałbym to zrozumieć a nie jedynie kopiuj wklej.

No to chwała Ci za to ;) W takim razie niech się wypowie ktoś, kto używa regexów regularnie, więc dla niego stworzenie odpowiedniej formuły to będzie chwila. Ja bym musiał mocno sobie temat odświeżyć i trochę w dokumentacji poszukać :(

Tak czy siak - pokazałem Ci (może trochę prowizoryczną, ale działającą) alternatywę, którą jesteś w stanie ogarnąć od ręki w ciągu dosłownie kilku minut. Możesz to zrobić w ten sposób, czekając na rozwiązanie z wyrażeniami regularnymi.

1

Ogarnąłem takim wyrażeniem:

 preg_match('/[0]\d{9}|\d{15}/', $sprawdzanyciag, $trafienia)
0
Draq napisał(a):

Ogarnąłem takim wyrażeniem:

 preg_match('/[0]\d{9}|\d{15}/', $sprawdzanyciag, $trafienia)

Czemu dla ciągu dziewięciu cyfr, Twój regex zaczyna je od zera, OP o tym nie pisał. Jeszcze było o spacjach; nie wiem czy takie coś w ogóle można zrobić regexem - musiałby "pamietać" ilość cyfr. Może spróbować tak: wyrażeniem:
[\d ]+
wyłowić wszystkie ciągi liczb ze spacjami, potem odfiltrować piętnasto i ewentualnie dziewięcio cyfrowe.

1

Ja kiedy ćwiczyłem regexpy przygotowałem sobie również małą ściągę, myślę, że pomoże:
https://github.com/ccwrc/ccwrc_knowledge_pills/blob/master/RegEx.txt

1

Sugeruję rozbić to sobie na kilka poleceń. Wyrażenia regularne to potężne narzędzie, które się koszmarnie czyta przy dłuższych tasiemcach.

usuń spacje

/\s*/g -> "" 

złap 15 cyfr

/[0-9]{15}/

jeśli powyższe nic nie złapało, złap 10 cyfr

/[0-9]{10}/

Ale to zadziała tak, że złapie początkowy fragment każdego ciągu liczbowego mającego minimum 15 lub 10 znaków.
Jeśli zależy ci, żeby złapało 15 cyfr obok siebie, ale nie złapało początkowego fragmentu 16+ cyfr, to:

[^0-9]([0-9]{15})[^0-9]
[^0-9]([0-9]{10})[^0-9]

A jeśli zależy ci na faktycznym wydobyciu tych cyfr a nie tylko stwierdzeniu faktu obecności to w wyrażeniu wyjściowym użyj pierwszego atmu $1.

0

Spokojnie i łatwo da się to zrobić jednym wyrażeniem:

((?:\d\s*){15})? - ((Cyfra i dowolna ilość spacji) * 15) opcjonalne

[\w\s]*? - Jakieś litery i spacje (non-greedy)

((?:\d\s*){9})? - ((Cyfra i dowolna ilość spacji) * 9) opcjonalne

Wszystko razem:

/^((?:\d\s*){15})?[\w\s]*?((?:\d\s*){9})?$/

Pierwsza grupa złapie (jeśli w ogóle) pierwsze 15 znaków, druga pozostałe (jeśli w ogóle) 9.

0

Ostatni regex łapie również litery:
https://regex101.com/r/wXBmE3/1

0
lion137 napisał(a):

Ostatni regex łapie również litery:
https://regex101.com/r/wXBmE3/1

Niby jak \d. Miałby złapać litery? Najwyżej cały match łapie litery w \w\s, ale tak ma być. W pierwszej grupie jest Twoja 15tka, w drugiej 9tka. Grupa 0 (cały match) możesz olać.

0
lion137 napisał(a):

Dałęm link

No tak, to co pokazałeś to jest cały match - grupa 0. Twój wynik będzie w grupie 1 i 2.

Twój podmiot z linka nie pasuje do mojego wzoru, bo napisałeś że ma być 15 cyfr, jakiś syf i 9 cyfr.

Jeśli chcesz żeby wzór pasował usuń $ z końca.

0

usuń spacje /\s*/g -> ""

Najlepiej zrobić to za pomocą str_replace. Poza tym, \s to nie tylko spacja i zamiast * powinien być +.

/^((?:\d\s*){15})?[\w\s]*?((?:\d\s*){9})?$/

Ten wzorzec nie działa nawet na przykładach podanych przez OPa.

0
Mózg napisał(a):

Ten wzorzec nie działa nawet na przykładach podanych przez OPa.

My bad, nie wziął pod uwagę że w rozumieniu OP "jakieś litery" to też -. Poprawiony wzorzec:

((?:\d\s*){15})?[a-zA-Z\s-]+((?:\d\s*){9})?

Miałeś rację również z +, zamiast *.

0

Poprawiony wzorzec

Przykład 1: 12 qwerty 999 999 999 999 999przyklad

array(3) {
  [0] => string(20) " qwerty 999 999 999 "
  [1] => string(0) ""
  [2] => string(12) "999 999 999 "
}

Przykład 2: 8664saad--031031502sadad560IMEI866431031502560 Reklamacja naprawy

array(3) {
  [0] => string(15) "saad--031031502"
  [1] => string(0) ""
  [2] => string(9) "031031502"
}

Testujesz swoje rozwiązania, czy lecisz na czuja?

0

@Mózg:

Już kumam, kiedy autor mówił

najpierw 15, potem 10 jeśli nie znajdzie podciągu o długości 15 cyfr.

to tak na prawdę to "potem" miało znaczy "a jeżeli nie"

((\d\s*){10}((\d\s*){5})?)

To znajdzie ciąg 15 cyfr, chyba że tylu nie ma wtedy zostawi 10 cyfr.

0

Już kumam

Troll?

array(4) {
  [0] => string(19) "999 999 999 999 999"
  [1] => string(1) "9"
  [2] => string(6) "99 999"
  [3] => string(1) "9"
}
array(4) {
  [0] => string(16) "866431031502560 "
  [1] => string(1) "5"
  [2] => string(6) "02560 "
  [3] => string(2) "0 "
}

Prawidłowe wyniki:

array(1) {
  [0] => string(15) "999999999999999"
}
array(1) {
  [0] => string(15) "866431031502560"
}
0
Mózg napisał(a):
array(4) {
  [0] => string(19) "999 999 999 999 999"
  [1] => string(1) "9"
  [2] => string(6) "99 999"
  [3] => string(1) "9"
}
array(4) {
  [0] => string(16) "866431031502560 "
  [1] => string(1) "5"
  [2] => string(6) "02560 "
  [3] => string(2) "0 "
}

Grupy 0 to są docelowe dane (tylko trzeba wywalić spacje).

Prawidłowe wyniki:

array(1) {
  [0] => string(15) "999999999999999"
}
array(1) {
  [0] => string(15) "866431031502560"
}

Noo, samymi regexpami tak się nie da. Nie dasz rady z preg_match() zwrócić kawałka tekstu którego nie ma w podmiocie (a 999999999999999 nie ma - najwyżej jest 999 999 999 999 999).

Najwyżej możesz usunąć spacje z grupy 0.

0

Noo, samymi regexpami tak się nie da.

Wczoraj napisałeś, że spokojnie i łatwo da się to zrobić jednym wyrażeniem. Poddajesz się?

0
Mózg napisał(a):

Noo, samymi regexpami tak się nie da.

Wczoraj napisałeś, że spokojnie i łatwo da się to zrobić jednym wyrażeniem. Poddajesz się?

Źle zrozumiałem pytającego. A "spokojnie i łatwo" odniosłem się bardziej do odpowiedzi wyżej, gdy ktoś proponował kilka wzorców na raz, co jest zupełnie nie potrzebne bo wystarczy jedna funkcja php żeby przerobić jedno w drugie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1