Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wyrażenie regularne na liczby
Forum PHP.pl > Forum > PHP
DNMX
Jakim wyrażeniem wydobędę z czegoś takiego:
Kod
Długość: 12,5 cm
Szerokość 20cm
Pojemność 0,7 L
Waga 1.5 kg

Liczby:
12,5
20
0,7
1,5
?
Salvation
Kod
/\d+(?:(?:,|\.)\d+)?/guim
DNMX
Ok a w czymś takim:
var_dump($data)
Kod
array(1) {
  ["items"]=>
  array(5) {
    [0]=>
    array(2) {
      ["label"]=>
      string(21) "Długość opakowania"
      ["value"]=>
      string(4) "1 cm"
    }
    [1]=>
    array(2) {
      ["label"]=>
      string(21) "Wysokość opakowania"
      ["value"]=>
      string(6) "2.3 cm"
    }
    [2]=>
    array(2) {
      ["label"]=>
      string(22) "Szerokość opakowania"
      ["value"]=>
      string(5) "20 cm"
    }
    [3]=>
    array(2) {
      ["label"]=>
      string(11) "Waga brutto"
      ["value"]=>
      string(8) "0.149 kg"
    }
    [4]=>
    array(2) {
      ["label"]=>
      string(25) "Liczba sztuk w opakowaniu"
      ["value"]=>
      string(4) "NULL"
    }
  }
}

  1. foreach($data['items'] as $item) {
  2. if(preg_match('/Szerokość/i', $item['label'])) {
  3. $Width = preg_match('/\d+(?:(?:,|\.)\d+)?/guim', $item['value'], $Width);
  4. echo "############" .$Width." #################";
  5. }
  6. }

Wyrzuca PHP Warning: preg_match(): Unknown modifier 'g' in i daje pustą wartość.
Kod
############ #################
trueblue
preg_match nie przeszukuje globalnie, od tego jest preg_match_all
Sprawdź też trzeci parametr preg_match.
DNMX
Zauważyłem, 3-ci parametr niepotrzebyn. Usunąłem ale wciąż to samo.

Co to znaczy nie przeszukuje globalnie? Mam użyć teg preg_match_all? Sorry ale jestem początkujący jeśli chodzi o wyrażenia regularne. Szukam raczej gotowca z wyjaśnieniem.
trueblue
Mógłbyś zajrzeć w dokumentację.
Dla preg_match_all jest wyjaśnienie:
Cytat
Searches subject for all matches to the regular expression given in pattern and puts them in matches...

Jeśli nie potrzebujesz wyszukiwać wszystkich liczb w stringu, lecz jeden, to wystarczy preg_match. A skoro preg_match nie przyjmuje parametru 'g', to znaczy, że ma go tam nie być.

Trzeci parametr funkcji jest porzebny, a wobec powyższego jego usuwanie nie jest rozwiązanie problemu.
kreatiff
Spróbuj tak pokombinować (chodzi o wyciąganie tych danych z tablicy):
  1. $x = array_map(fn($i) => preg_replace('#[^0-9\,\.]#', '', $i), array_column($data, 'value'));
DNMX
Z preg_replace zadziałało. Dzięki!
trueblue
Jeśli oprócz wartości pojawi się cyfra w innym miejscu, np. w jednostce (cm2), to wynik będzie błędny.
kreatiff
Słuszna uwaga od trueblue.
Jeśli taka sytuacja zachodzi, to trzeba będzie doprecyzować wyrażenie, by np. wycinało wszystko co jest po pierwszej spacji lub literze. Zależy jakie wartości mogą pojawić się w 'value'.
DNMX
Jeszcze jedno pytanie w temacie. Zanim wyjdzie mi taka ładna tablica jak w drugim poscie, wykonuję json_decode() na $raw_json który jest stringiem:
Kod
string(314) "{"items":[{"label":"Długość opakowania","value":"1.5 cm"},{"label":"Wysokość opakowania","value":"16 cm"},{"label":"Szerokość opakowania","value":"4.5 cm"},{"label":"Waga brutto","value":"0.08 kg"},{"label":"Wymiary produktu","value":"szer. ostrza 18 mm"},{"label":"Liczba sztuk w opakowaniu","value":"10"}]"

W przypadku powyżej wszystko jest OK ale w takim przypadku:
Kod
string(254) "{"items":[{"label":"Długość opakowania","value":bi},{"label":"Wysokość opakowania","value":"3.75 cm"},{"label":"Szerokość opakowania","value":bi},{"label":"Waga brutto","value":"0.891 kg"},{"label":"Wymiary produktu","value":"3,7 x 3,5 x 3,5 cm"}]"

funkcja json_decode() zwraca pustą tablicę (NULL). Domniemuję, że to dlatego, iż niektóre wartości przyjmują wartość innej zmiennnej, jak np. bi albo bk, bd itp. Zastanawiam się, jak to ominąć. Jedyne co przychodzi mi do głowy to wyrażenie regularne które zamieni
Kod
"value":bi}
"value":bk}
"value":bd}

na
Kod
"value":"0.00"}

Innymi słowy, wartości, które nie są wyescapowane (zaczynają i kończą się na ") zamienić na "0.00". Da się na to stworzyć jakieś wyrażenie regularne?
Salvation
Pomijając problem niezamkniętej klamry na końcu, to jeżeli te `bi`, `bk` i `bd`, to stałe, to możesz użyć takiego kodu:
  1. preg_replace('/\:b(?:i|d|k)}/ui', ':"0.00"}', $jsonString);
DNMX
To tylko przykłady nazw stałych. Jest ich mnóśtwo wiecej niż bi, bk i bd. Nazwy różnej długości. Dlatego też chciałem łapać wszystko, co nie ma klamry.
trueblue
Dodając cudzysłowy do bk, bi, itd., wynik parsowania jest poprawny.


Takiego stringa: 3,7 x 3,5 x 3,5 cm nie przetworzysz na wartość liczbową przy pomocy preg_replace.
DNMX
Wiem o tym dlatego szukam regexpa, który zamieni "value":bi} na "value":"bi"}, "value":bk} na "value":"bk"} itd, itp. Ogólnie mówiąc, to co występuje po "value", a } i doda do tego " "
Salvation
No dobra, to takie coś:
  1. preg_replace('/"value":([a-z]+)}/ui', '"value":"${1}"}', $jsonString);

Demo: https://3v4l.org/7QBET
DNMX
O dzięki, właśnie o coś takiego chodziło! Zadziałało, w sensie zmienia wartość value na "value" ale cały skrypt wypluwa jeszcze errory. Zauważyłem, że są też labele bez "":
Kod
string(331) "{"items":[{"label":[b]bx[/b],"value":"by"},{"label":"Grubość produktu","value":"18 mm"},{"label":"Wysokość produktu","value":"71,5 cm"},{"label":"Waga brutto","value":"4.86 kg"},{"label":"Szerokość opakowania","value":"80.5 cm"},{"label":"Wysokość opakowania","value":"2.3 cm"},{"label":"Długość opakowania","value":"50.3 cm"}]"
NULL

Zmodyfikowałem analogicznie kod:
  1. $data = preg_replace('/"label":([a-z]+)}/ui', '"label":"${1}"}', $data);

ale wypluwa to samo co u góry. Co jeszcze robię nie tak?
viking
Trochę nie rozumiem co ty robisz. Json jest albo poprawny, albo nie i wtedy jego poprawianie nie ma sensu. Teraz poprawisz 10 rzeczy a zaraz będzie kolejna zła. Zabawa bez sensu.
DNMX
Radzę sobię, jak mogę. To nie jest JSON tylko fragment skryptu wycięty ze źródła strony. Takie dane niestety dostaję
Salvation
Spróbuj takie coś. Koniecznie w tej kolejności:
  1. $jsonString = preg_replace('/":\[\w\]([a-z]+)\[\/\w\]/ui', '":${1}', $jsonString);
  2. $jsonString = preg_replace('/":([a-z]+)(,|})/ui', '":"${1}"${2}', $jsonString);

Demo: https://3v4l.org/CPlf9
DNMX
Dzięki, o to właśnie chodziło! W niektórych plikach miałem jeszcze a$ jako nazwę zmiennej. Zmodyfikowałem wyrażenie na
  1. $data2 = preg_replace('/":\[\w\]([a-z$]+)\[\/\w\]/ui', '":${1}', $data2);
  2. $data2 = preg_replace('/":([a-z$]+)(,|})/ui', '":"${1}"${2}', $data2);
i teraz 99,7% wsadów przetwarzana jest prawidłowo.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.