2016-08-08 5 views
0

in vereinfachter Form, bin ich versucht, entweder das erste Auftreten des '.*?=(.*?);.*' regex, oder die zweite oder die dritte abzurufen - das heißt, entweder x oder y oder z (das heißt, ich will in dieser Abfrage codieren können, dass ich die ersten, zweite oder dritte Werte will) in diesem folgende Beispiel:Retrivieng spezifischen Vorkommen eines gegebenen Regex mit Oracle SQL

select regexp_replace(
    'margin=x;margin=y;margin=z;', 
    '.*?=(.*?);.*', 
    '\1', 
    1 -- occurrences. I thought that picking 1, 2 or 3 would solve my problem? 
) from dual; 

-- This returns "xyz", which is terrible. I was expecting it to return "x", in this case. 

mit Blick auf der Oracle-Dokumentation, dachte ich, das relativ wäre Geradeaus, als der letzte Parameter (Vorkommen), erlaubt mir scheinbar auszuwählen, welche Gruppen berücksichtigt werden sollen. Aber das tut es nicht! Warum?

Dank

+1

können Sie versuchen, '([^ =] * = (*);.?) {3} *' den dritten Wert zu erhalten.. Aber ersetzen Sie mit '\ 2'. Die Anzahl der Vorkommnisse sollte auf "0" gesetzt werden (nicht ganz wichtig, da die gesamte Zeichenfolge nur einmal abgeglichen wird). –

+0

@ WiktorStribiżew: Scheint nicht zu funktionieren? Gibt nur die ganze Zeichenfolge aus? –

+0

Haben Sie versucht mit '([^ =] * = (. *?);) {2}. *'> '\ 2'? Ich denke auch, dass "(. *? = (. *?);) {3}. *" Auch funktionieren sollte. –

Antwort

0

Sie benötigen einen regulären Ausdruck, die 1-n Vorkommen der gesamten Gruppe übereinstimmen. Z.B.

([^=]*=([^;]*);){2}.* 

(mit \2 Rückreferenzierung ersetzt) ​​wird den zweiten Attributwert erhalten. Ihre Regex kann auch verwendet werden (obwohl es auch zu dem obigen Muster ist): (.*?=(.*?);){2}.*.

Siehe regex demo

Wenn Sie die Indexvariable als IDX definieren, Sie so etwas wie

select regexp_replace(
    'margin=x;margin=y;margin=z;', 
    CONCAT('([^=]*=([^;]*);){', IDX, '}.*'), 
    '\2' 
) from dual; 

HINWEIS verwenden können: Wenn Sie einen leeren String als Ergebnis erhalten wollen versuchen, einen nicht vorhandenen Wert, fügt |.* am Ende der Regex erhalten:

(.*?=(.*?);){4}.*|.* 

Siehe this regex demo (mit Ihrer Eingabezeichenfolge ist das Ergebnis eine leere Zeichenfolge).

1

Ich gehe zu einer ganz anderen Lösung. Wäre das Kombinieren eines hierarchischen Teilstrings mit einem regexp_replace eine Option für Ihre Bedürfnisse?

Auf diese Weise können Sie eine Option erstellen, um je nach Bedarf einen oder mehrere Werte auszuwählen. Sie würde nicht brauchen einen concatinating regex Wert zu schreiben, und man konnte die Auswahl ein bisschen mehr auf Ihre Bedürfnisse

select regexp_replace(subselect.val, '.*=(.*?);', '\1') -- remove "margin=" 
from (select regexp_substr(
      'margin=x;margin=y;margin=z;', 
      '.*?=(.*?);', 
      1, 
      level) val, 
      level lvl 
     from dual 
     connect by regexp_substr('margin=x;margin=y;margin=z;', 
           '.*?=(.*?);', 
           1, 
           level) is not null) subselect -- This select represents each margin=T as a single row 
where lvl = 1; -- cou could define multiple values to select aswell. 
1

Vielleicht alles, was Sie einstellen müssen, ist diese .... Der vierte Parameter ist nicht das Auftreten aber die Position von dem die Suche startet. Der FIFTH-Parameter ist das Auftreten.

https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions130.htm

Auch Sie sind sicher, dass Sie ersetzen möchten und SubStr nicht?

EDITED: Um zu klären (es scheint mindestens eine Person war verwirrt). Ich zeige eine mögliche Lösung für das, was Sie (vielleicht) am Ende brauchen, aber zuerst schauen wir uns REGEXP_REPLACE an. Ich habe Ihre Abfrage neu geschrieben, um verschiedene Vorkommen zu verwenden. Ich lege den Index in einen CTE, aber Sie können stattdessen idx in eine Bind-Variable oder einen anderen Mechanismus, den Sie verwenden müssen, setzen. Wie Sie sehen werden, macht die Ausgabe keinen Sinn.

with t1 (idx) as (select 1 from dual union all select 2 from dual 
             union all select 3 from dual) 
select idx, 
     regexp_replace('margin=x;margin=y;margin=z;', '.*?=(.*?);.*', '\1', 1, idx) as val 
from t1; 

Ausgang:

 IDX VAL 
---------- ----------------------- 
     1 xmargin=y;margin=z; 
     2 margin=x;ymargin=z; 
     3 margin=x;margin=y;z 

3 rows selected. 

Ich denke, das ist nicht das, was man braucht - aber es zeigt, was in Ihrer Abfrage falsch war. Das vierte Argument für REGEXP_REPLACE, 1 in allen Fällen in der obigen Abfrage, ist die Position, von der aus die Suche beginnt. Das fünfte Argument, idx, ist das Auftreten. Diese Abfrage ersetzt das erste, zweite und dritte Vorkommen durch den Unterausdruck - wahrscheinlich nicht das, was Sie wollten.

Wenn Sie x extrahieren müssen, oder y oder z, abhängig von der Anzahl der Vorkommen, müssen Sie REGEXP_SUBSTR verwenden, nicht REGEXP_REPLACE. Beachten Sie auch, dass ich das Matchmuster geändert habe - die .*? am Anfang und die .* am Ende sind unnötig. Wenn Sie x, y oder z in etwas wie margin=x;, aber nicht in length=x; finden möchten, müssen Sie dies explizit machen, das Übereinstimmungsmuster sollte 'margin=(.*?);' sein.

with t1 (idx) as (select 1 from dual union all select 2 from dual 
             union all select 3 from dual) 
select idx, 
     regexp_replace('margin=x;margin=y;margin=z;', '=(.*?);', '\1', 1, idx) as val 
from t1; 

Ausgang:

 IDX VAL 
---------- ------- 
     1 x 
     2 y 
     3 z 
+0

Wer auch immer du bist (ich sehe einen Downvote und eine Stimme, um meine Antwort zu löschen): Es wäre hilfreich für mich und die Gemeinschaft, wenn du erklären möchtest, was mit dieser Antwort falsch ist. – mathguy

Verwandte Themen