Teknologian jakaminen

? säännöllisissä lausekkeissa

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Säännöllisissä lausekkeissa,? Se voi edustaa määrää, 0 tai 1 kertaa, mikä vastaa arvoa 0, 1}, tai sitä voidaan käyttää erikoismerkkinä edustamaan muita merkityksiä.

ei-ahne haku

?, jota seuraa muut määrän tarkenteet, tarkoittaa ei-ahnetta hakua, toisin sanoen vastaavuutta lyhimmän mahdollisen merkkijonon kanssa.

Katsotaanpa esimerkkiä:

  1. @Test
  2. public void test() {
  3. Pattern pattern = Pattern.compile("a.*?");
  4. Matcher matcher = pattern.matcher("abcabc");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. }
  8. }

Tulos suoritus suorituksen jälkeen: abcabc

Eikö se ole lyhin ottelu? Miksi se epäonnistui?

Tämä sisältää itse asiassa ei-ahneen vastaavuuden säännöt:Ei-ahneessa sovituksessa lyhin polku sovitetaan ennen seuraavaa sääntöä. Jos seuraavaa sääntöä ei ole, se käsitellään ahneeksi sovitukseksi.

Toisin sanoen, jos vain "a.*?", se käsitellään silti ahneen vastaavuuden mukaan.

Katsotaanpa oikeaa käyttöä:

  1. @Test
  2. public void test() {
  3. Pattern pattern = Pattern.compile("(a.*?)(.*)");
  4. Matcher matcher = pattern.matcher("afcafc");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group(0));
  7. System.out.println(matcher.group(1));
  8. System.out.println(matcher.group(2));
  9. }
  10. }

Tulos suoritus suorituksen jälkeen:

  1. afcafc
  2. a
  3. fcafc

Kuten näet, ensimmäinen sieppausryhmä kaappaa lyhimmän merkkijonon "a" ja toinen sieppausryhmä kaappaa "fcafc".

Katsotaanpa kahta muuta tilannetta:

  • "(a.*)(.*)" Ensimmäinen sieppausryhmä kaappaa kaiken, toinen kaappausryhmä ei ilmoita virheestä, mutta ei sieppaa mitään.
  • "(a.*?)(.*?)" Ensimmäinen sieppausryhmä kaappaa "a" ja toinen kaappausryhmä "fcafc", koska myöhemmin ei ole muita sääntöjä, se käsitellään ahneella vastaavuudella .

Yhdistä, mutta älä kaappaa (?:pattern)

Sieppausryhmässä käytettynä ?: sijoitetaan ennen säännöllistä lauseketta osoittamaan täsmäämistä, mutta ei kaappausta, eli tätä yhteensopivien arvojen ryhmää ei voida saada ryhmämenetelmällä.

Katsotaanpa esimerkkiä

  1. @Test
  2. public void test0() {
  3. Pattern pattern = Pattern.compile("\d{4}-(?:[a-z]+)");
  4. Matcher matcher = pattern.matcher("3214-opo");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. System.out.println(matcher.group(1)); // 报错
  8. }
  9. }

Virhe raportoidaan kaapattaessa ryhmän(1) kautta, eli se voidaan sovittaa, mutta sitä ei voi siepata. Jos ?: poistetaan, se voidaan kaapata normaalisti ryhmän (1) kautta.

Ota yksirivinen tila (?s) käyttöön

(?s) ottaa käyttöön yksirivisen tilan oikealla puolella, mikä vastaa mitä tahansa merkkiä, myös rivinvaihtomerkkiä n.

Katsotaanpa esimerkkiä:

  1. private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)";
  2. /**
  3. * 从输出结果可知,匹配到了换行符 'n'
  4. */
  5. @Test
  6. public void test4() {
  7. Pattern pattern = Pattern.compile(DEFAULT_VARIABLE_PATTERN);
  8. Matcher matcher = pattern.matcher("abcnsdf");
  9. if (matcher.matches()) {
  10. System.out.println(matcher.group());
  11. System.out.println(matcher.group(1));
  12. System.out.println(matcher.group(2)); // (?s) 不能作为捕获组,报错
  13. }
  14. }

Sieppauksen aikana (?s) ei voi kaapata kaappausryhmänä, joten "(?s).*)" voi kaapata enintään ryhmän(1), ja ryhmä(2) kaapattaessa raportoidaan virhe.

  1. @Test
  2. public void test5() {
  3. Pattern pattern = Pattern.compile("(.*)");
  4. Matcher matcher = pattern.matcher("abcnsdf");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. System.out.println(matcher.group(1));
  8. }
  9. }

Kun olet poistanut (?s), yritä sovittaa "abcnsdf", koska rivinvaihtomerkkiä ei voida suorittaa loppuun, joten mitään ei tulosteta.