Regex - wyrażenie regularne do wyłuskania wartości liczbowych

0

Witam, mam problem z wyrażeniami regularnymi w C++. Przeczytałem sporo tutoriali i po wielu próbach nie rozumiem pewnych rzeczy. Mam prosty kod HTML:

<span id="resources_cos" class="">
                        17.555                    </span>

...

<span id="resources_innego" class="">
                        3.555                    </span>

...

<span id="resources_zupelnie" class="">
                        155.5                    </span>

I chcę z tego kodu wyłuskać wartości liczbowe. Próbowałem na wiele sposobów i przeważnie nic nie zwracało. Co mnie jednak zastanawia to to że jeżeli dam taki pattern jak poniżej:

std::regex pattern("<span id=\"resources_[a-z]+");

to nie zwraca mi wszystkich trzech pasujących do patternu "spanów" a tylko ten pierwszy. Dodatkowo nie wiem jak mam opisać ten środek (wart. liczbową) żeby mi ją znalazło, również próbowałem na różne sposoby ale nic z tego.

Pozdrawiam
Sheppard25

0

Regex to <span.+?id="resources_[a-z]+".+?>.+?([0-9.]+).+?</span>, a wyszukiwanie będzie w taki sposób:

std::string s ("this subject has a submarine as a subsequence");
std::smatch m;
std::regex e ("<span.+?id=\"resources_[a-z]+\".+?>\\s*([0-9.]+)\\s*</span>");

while (std::regex_search(s, m, e)) {
  std::cout << m[1] << '\n';
}
0

Znam się na C++ jak jeden user tutaj na t. na kulturze, ale o ile coś tam się nauczyłem przy regexprach kodząc w delphi, to ja bym zrobił tak
<span id="resources_(.+?)>(.+?)([0-9\.]+)(.+?)</span>
To co potrzebujesz będzie w Match[3] jeśli nie załapie z kropką to dawaj zawsze \x i kod znaku w hex. Nie mam jak tego teraz dobrze sprawdzić, bo piszę z tabletu.

0

@winerfresh, dzięki za odpowiedź, pattern wygląda poprawnie, niestety nie znajduje. Być możę przyczyną jest nieuwzględnienie białych znaków oraz znaku przejścia do nowej linii (kod w notepadzie++ wygląda dokładnie tak jak w moim 1 poście, masa spacji (czy innych tabulatorów). Dodałem niby obsługę tego ale chyba źle bo nadal nie znajduje.

@olesio, dzięki za to że chciało Ci się na tablecie klepać te znaczki, jeżeli to czysty Android to pewnie Ci ciągle przeskakiwało do [A-Z] w klawiaturze :] Niestety, Twój kod także nie działa choć chyba zawiera obsługę białych znaków (ale bez przejścia do nowej linii).

Temat otwarty, próbuję kombinacji Waszych kodów, na razie bezskutecznie

0

@winerfresh, niestety. Próbowałem też z wersją uproszczoną z dodanym przejściem do nowej lini:

("<span id=\"resources_[a-z]+\" class=\"\">\s*([0-9.]+)\s*\n\s*</span>");

ale też nie idzie. Dodatkowo wywala warninga

warning C4129: 's' : unrecognized character escape sequence
0

Niestety, tak też nie działa. Chyba jednak zrobię to zwykłym find-em i substr-em z klasy Stringa bo nie ma sensu się z tym męczyć drugi dzień. Może i wydajnościowo trochę poleci, ale tymczasowo niech będzie.

@Azarien tak, wiem, ale w tym stringu nie ma slashy. Są tylko "/" do których nie trzeba dawać podwójnie

0

Jeżeli standard wyrażeń regularnych C++ jest podobny do Delphi to może być mniej więcej coś takiego: <span id="resources_[^"]+" class="">[^0-9]+([0-9\.]+)[^<]+<\/span> lub <span id="resources_[^"]+" class="">[^0-9]*?([0-9\.]+)[^<]*?<\/span> jeżeli te spacje i znaki nowej linii mogą ale nie muszą wystąpić. Tylko w C++ to chyba trzeba dodać \ przed " a tam gdzie jest \ to chyba ma być 2 nie znam się.

0

@kAzek ma rację, zdarzają się znaki tabulacji w HTMLu (czyli \x09 dla wyrażeń regularnych). Ja tylko poniżej wkleje kod Delphi, więc niech żadne C++'sowcy nie rozpoczynają mi tutaj flame'a proszę, jak ostatnio w wątku o tym, w czym napisać AutoUpdater'a. Poniższy kod działa. A ja dzięki @kAzek'owi dowiedziałem się jak używać ^ w wyrażeniach regularnych, A moje wyrażenie, które podałem powyżej - poprawiłem. Jakby @Sheppard25 dojrzał, że barkuje " przed resources, to jakby go dopisał było by ok. Oczywiście użyty moduł to ten z: http://regexpstudio.com/TRegExpr/TRegExpr.html

uses
  regexpr;
//...
var
  S : string;
  R : TRegExpr;
begin
  S := Memo1.Text;
  Memo1.Clear;
  R := TRegExpr.Create;
  try
    R.Expression := '<span id="resources_[^"]+" class="">[^0-9]+([0-9\.]+)[^<]+</span>';
    if R.Exec(S) then
    begin
      repeat
        Memo1.Lines.Add(R.Match[1]);
      until not R.ExecNext;
    end;
  finally
    R.Free;
  end;
end;

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