Regex, aby dopasować ciąg zawierający dwie nazwy w dowolnej kolejności


180

Potrzebuję logicznego AND w wyrażeniu regularnym.

coś jak

jack AND james

zgadzają się z następującymi ciągami

  • „cześć jack, tu jest james

  • „cześć james, tu jest jack



@AndersonGreen, pytanie zostało przedwcześnie zablokowane. Poważnie brakuje odpowiedzi, ponieważ te rozwiązania nie są wykonalne, ponieważ większość wyrażeń regularnych nie rozpoznaje obejścia i kwantyfikatora trybu . Uważam, że kwantyfikator istniał w momencie zadawania pytania.
XPMai

Odpowiedzi:


261

Możesz sprawdzić, używając lookarounds :

^(?=.*\bjack\b)(?=.*\bjames\b).*$

Sprawdź to.

Takie podejście ma tę zaletę, że można łatwo określić wiele warunków.

^(?=.*\bjack\b)(?=.*\bjames\b)(?=.*\bjason\b)(?=.*\bjules\b).*$

18
Czy ktoś mógłby wyjaśnić bardziej szczegółowo, jak działa ten przykład?
bjmc

2
vimskładnia: ^\(.*\<jack\>\)\@=\(.*\<james\>\@=\).*$lub\v^(.*<jack>)@=(.*<james>)@=.*$
mykhal

Czy ktoś wie, dlaczego to się psuje (przynajmniej w JavaScript), gdy próbuję wyszukać ciągi zaczynające się od „#”? ^(?=.*\b#friday\b)(?=.*\b#tgif\b).*$nie pasuje, blah #tgif blah #friday blahale ^(?=.*\bfriday\b)(?=.*\btgif\b).*$działa dobrze.
btleffler

2
Co to \bznaczy?
VarunAgw


106

Próbować:

james.*jack

Jeśli chcesz mieć oba jednocześnie, to orone:

james.*jack|jack.*james

1
Przyjęta odpowiedź zadziałała. to również działało idealnie dla mnie. Do wyszukiwania kodu w programie Visual Studio „znajdź wyniki”.
Jogurt The Wise

1
Ten działa dla mnie i jest znacznie bardziej zwięzły i łatwy do zrozumienia niż zaakceptowana odpowiedź!
Kumar Manish

1
Potrzebowałem rozwiązania, które ma tylko dwie nazwy do dopasowania, więc ta odpowiedź jest bardziej zwięzła w tym przypadku. Ale przyjęta odpowiedź staje się bardziej zwięzła powyżej 2, ponieważ liczba „lub” rośnie silnie. Dla 3 nazw byłoby 6 "lub" s, 4 nazwy miałyby 24 "lub" s itd.
WileCau

Poleciłbym rozlenić james.*?jack|jack.*?james . Pomoże to w przypadku dużych tekstów.
Jekis

42

Wyjaśnienie polecenia, które mam zamiar napisać : -

. oznacza dowolny znak, cyfra może zastąpić.

* oznacza zero lub więcej wystąpień rzeczy napisanej tuż przed tym.

|oznacza „lub” .

Więc,

james.*jack

przeszuka james , a następnie dowolną liczbę znaków, aż jacknadejdzie.

Ponieważ chcesz albo jack.*jameslubjames.*jack

Stąd polecenie :

jack.*james|james.*jack

7
Na marginesie - mogłeś również edytować odpowiedź @ icyrock (która jest taka sama jak twoja, zaledwie 6 lat wcześniej), twoje wyjaśnienie jest samo w sobie bardzo przydatne.
WoJ

2
Dziękuję za tę odpowiedź, czuję jednak potrzebę zwrócenia uwagi, że w wyszukiwaniu VSCode jest to gniazdo odpowiedzi . * James | james. * jack zajmie spacje między znakami „|” (lub) symbol brany pod uwagę podczas wyszukiwania. jack. * james | james. * jack działa i nie szuka spacji
jgritten

2
JEŚLI $ _explanation === "niesamowite", TO zwraca $ THUMBS_UP ENDIF;
Syed Aqeel



2

Vim ma operatora oddziału \& który jest przydatny podczas wyszukiwania linii zawierającej zestaw słów w dowolnej kolejności. Ponadto rozszerzenie zestawu wymaganych słów jest banalne.

Na przykład,

/.*jack\&.*james

dopasuje wiersz zawierający jacki james, w dowolnej kolejności.

Zobacz tę odpowiedź, aby uzyskać więcej informacji na temat użytkowania. Nie znam żadnego innego rodzaju wyrażenia regularnego, który implementuje rozgałęzianie; operator nie jest nawet udokumentowany we wpisie w Wikipedii dotyczącym wyrażeń regularnych .


2

METODA 1: Jeden jacki jedenjames

Na wszelki wypadek, dwa jacklub dwa jamesbyłyby niedozwolone, tylko jeden jacki jeden jamesbyłby ważny, prawdopodobnie możemy zaprojektować wyrażenie podobne do:

^(?!.*\bjack\b.*\bjack\b)(?!.*\bjames\b.*\bjames\b)(?=.*\bjames\b)(?=.*\bjack\b).*$

Tutaj wykluczylibyśmy te wystąpienia par, używając następujących instrukcji:

(?!.*\bjack\b.*\bjack\b)

i,

(?!.*\bjames\b.*\bjames\b)

Demo RegEx 1

Możemy to również uprościć,

^(?!.*\bjack\b.*\bjack\b|.*\bjames\b.*\bjames\b)(?=.*\bjames\b|.*\bjack\b).*$

RegEx Demo 2


Jeśli chcesz uprościć / zmodyfikować / zbadać wyrażenie, zostało to wyjaśnione w prawym górnym panelu regex101.com . Jeśli chcesz, możesz również obejrzeć w tym linku , jak to będzie się zgadzać z niektórymi przykładowymi danymi wejściowymi.


RegEx Circuit

jex.im wizualizuje wyrażenia regularne:

wprowadź opis obrazu tutaj

Test

const regex = /^(?!.*\bjack\b.*\bjack\b|.*\bjames\b.*\bjames\b)(?=.*\bjames\b|.*\bjack\b).*$/gm;
const str = `hi jack here is james
hi james here is jack
hi james jack here is jack james
hi jack james here is james jack
hi jack jack here is jack james
hi james james here is james jack
hi jack jack jack here is james
`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}


METODA 2: Jeden jacki jeden jamesw określonej kolejności

Może być również zaprojektowany jako pierwszy jamesostatni jack, podobny do następującego:

^(?!.*\bjack\b.*\bjack\b|.*\bjames\b.*\bjames\b)(?=.*\bjames\b.*\bjack\b).*$

RegEx Demo 3

i wzajemnie:

^(?!.*\bjack\b.*\bjack\b|.*\bjames\b.*\bjames\b)(?=.*\bjack\b.*\bjames\b).*$

RegEx Demo 4


0

Możesz skorzystać z funkcji kwantyfikatora wyrażeń regularnych, ponieważ lookaroundmoże nie być obsługiwana przez cały czas.

(\b(james|jack)\b.*){2,}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.