Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ PHP _ Wyrażenie regularne na liczby

Napisany przez: DNMX 27.01.2023, 22:39:19

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
?

Napisany przez: Salvation 27.01.2023, 23:40:25

Kod
/\d+(?:(?:,|\.)\d+)?/guim

Napisany przez: DNMX 30.01.2023, 10:02:00

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(http://www.php.net/preg_match('/Szerokość/i', $item['label'])) {
  3. $Width = http://www.php.net/preg_match('/\d+(?:(?:,|\.)\d+)?/guim', $item['value'], $Width);
  4. http://www.php.net/echo "############" .$Width." #################";
  5. }
  6. }

Wyrzuca PHP Warning: preg_match(): Unknown modifier 'g' in i daje pustą wartość.
Kod
############ #################

Napisany przez: trueblue 30.01.2023, 10:09:21

preg_match nie przeszukuje globalnie, od tego jest preg_match_all
Sprawdź też trzeci parametr preg_match.

Napisany przez: DNMX 30.01.2023, 10:15:59

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.

Napisany przez: trueblue 30.01.2023, 10:22:15

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.

Napisany przez: kreatiff 30.01.2023, 10:22:23

Spróbuj tak pokombinować (chodzi o wyciąganie tych danych z tablicy):

  1. $x = http://www.php.net/array_map(fn($i) => http://www.php.net/preg_replace('#[^0-9\,\.]#', '', $i), array_column($data, 'value'));

Napisany przez: DNMX 30.01.2023, 11:05:08

Z preg_replace zadziałało. Dzięki!

Napisany przez: trueblue 30.01.2023, 11:27:31

Jeśli oprócz wartości pojawi się cyfra w innym miejscu, np. w jednostce (cm2), to wynik będzie błędny.

Napisany przez: kreatiff 30.01.2023, 12:02:55

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'.

Napisany przez: DNMX 1.02.2023, 12:06:32

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?

Napisany przez: Salvation 1.02.2023, 13:22:29

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. http://www.php.net/preg_replace('/\:b(?:i|d|k)}/ui', ':"0.00"}', $jsonString);

Napisany przez: DNMX 1.02.2023, 13:49:22

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.

Napisany przez: trueblue 1.02.2023, 14:20:42

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.

Napisany przez: DNMX 1.02.2023, 22:11:32

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 " "

Napisany przez: Salvation 2.02.2023, 00:07:04

No dobra, to takie coś:

  1. http://www.php.net/preg_replace('/"value":([a-z]+)}/ui', '"value":"${1}"}', $jsonString);

Demo: https://3v4l.org/7QBET

Napisany przez: DNMX 2.02.2023, 07:07:32

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 = http://www.php.net/preg_replace('/"label":([a-z]+)}/ui', '"label":"${1}"}', $data);

ale wypluwa to samo co u góry. Co jeszcze robię nie tak?

Napisany przez: viking 2.02.2023, 07:57:26

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.

Napisany przez: DNMX 2.02.2023, 08:02:12

Radzę sobię, jak mogę. To nie jest JSON tylko fragment skryptu wycięty ze źródła strony. Takie dane niestety dostaję

Napisany przez: Salvation 2.02.2023, 09:43:24

Spróbuj takie coś. Koniecznie w tej kolejności:

  1. $jsonString = http://www.php.net/preg_replace('/":\[\w\]([a-z]+)\[\/\w\]/ui', '":${1}', $jsonString);
  2. $jsonString = http://www.php.net/preg_replace('/":([a-z]+)(,|})/ui', '":"${1}"${2}', $jsonString);

Demo: https://3v4l.org/CPlf9

Napisany przez: DNMX 2.02.2023, 10:32:13

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 = http://www.php.net/preg_replace('/":\[\w\]([a-z$]+)\[\/\w\]/ui', '":${1}', $data2);
  2. $data2 = http://www.php.net/preg_replace('/":([a-z$]+)(,|})/ui', '":"${1}"${2}', $data2);
i teraz 99,7% wsadów przetwarzana jest prawidłowo.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)