Refrex!ES2018의 캡처 및 비캡처 그룹

저는 최근에 Javascript에서 정규 표현식의 즐거움을 얻었고 유용한 것을 배웠습니다. 여러분과 공유하고 싶어서 Refrex라는 시리즈를 시작했습니다. 이것은 정규 표현식에 대한 복습입니다.

이것은 그리 나쁘지 않다, 그렇지?
어쨌든 우리는 기초 지식부터 시작해서 포획과 비포획조에 들어가자.
이것은 내가 가지고 있는 임무이다. 나는 특정 영역의 전체 호스트, 하위 영역과 URL 경로를 추출해야 한다(본 연습을 위해 사용하겠다google.com.
다음과 같은 모든 가능성에 대해 작업해야 합니다.
www.google.com/search?q=devto
//www.google.com
http://www.google.com
https://www.google.com/search?q=devto
mail.google.com
something.like.google.com/for-me
나는 정규 표현식에 대해 약간 생소하지만, 나는 몇 가지 일을 기억한다.
  • 정규 표현식은 두 개/로 구분된다.
  • 첫 번째와 두 번째/ 사이에 정규 표현식 모드를 배치하고 두 번째/ 다음에 로고를 배치합니다. 예를 들어 i 대소문자 삽입 또는 g 전역을 표시합니다.
  • 에는 줄 바꿈 문자를 제외한 모든 문자를 나타내는 문자 클래스가 있습니다.
  • 모드에서 일부 문자..를 사용하려면 문자류와 정규 표현식 구분자와 혼동되지 않도록 의미를 바꿔야 한다.그리고 use/\.를 사용해야 합니다.
  • 양사는 \/(0 또는 1회 출현), ?(0 또는 그 이상 출현), *(1 또는 그 이상 출현)이 있다.
  • 우리는 한 문자 뒤에 양사를 사용할 수 있다.
  • 전체 그룹에서 양사를 사용할 수 있도록 괄호를 사용하여 문자를 그룹화할 수도 있습니다.
  • 우리가 괄호를 사용하여 그룹을 형성할 때, 문자열의 + 함수를 사용할 때, 그것들도 포착되어 단독으로 되돌아온다.
  • 그래서 나는 이렇게 시작했다.
    const regex = /((https?:)?\/\/)?(.*)\.google\.com(.*)/i;
    
    우리는 그것을 몇 부분으로 분해합시다.우선, 협의:
  • match - 이것은 포획https? 또는http을 할 것이다.알파벳's'는 여기에서 선택할 수 있습니다. 왜냐하면 우리가 사용하기 때문입니다https.
  • s? - 전체 그룹이 선택할 수 있기 때문에 포획(https?:)?, http: 또는 아무것도 포획하지 않습니다.
  • https: - 슬래시 캡처 프로토콜을 사용합니다. 슬래시는 ((https?:)?\/\/)?, http://, https:// 또는 아무것도 아닙니다. 전체 그룹은 선택할 수 있기 때문입니다.
  • 이제 나머지 부분에 대해서는
  • // - 하위 도메인 캡처
  • (.*) - 일치 \.google\.com
  • .google.com - 경로 캡처
  • 따라서 이 정규 표현식과 함께 (.*) URL을 사용할 때 다음과 같은 결과를 얻을 수 있습니다.
    'https://www.google.com/search?q=devto'.match(regex);
    
    // Result:
    {
      0: "https://www.google.com/search?q=devto",
      1: "https://",
      2: "https:",
      3: "www",
      4: "/search?q=devto",
      groups: undefined,
      index: 0,
      input: "https://www.google.com/search?q=devto",
      length: 5
    }
    
    반환된 개체에서 요소 0은 완전히 일치하는 결과이며, 그 다음의 모든 디지털 요소는 정규 표현식에 나타난 각 포획 그룹에 순서대로 대응합니다.
    지금까지는 3조의 하위 영역, 4조의 경로, 1조+match+4조를 조합한 전체 호스트를 볼 수 있었기 때문에 지금은 다음과 같은 함수를 작성할 수 있습니다.
    function extract(url) {
      const regex = /((https?:)?\/\/)?(.*)\.google\.com(.*)/i;
    
      const match = url.match(regex);
    
      let result = {};
      if (match !== null) {
        result = {
          host: `${match[1]}${match[3]}.google.com`,
          subdomain: match[3],
          path: match[4]
        };
      }
    
      return result;
    }
    
    그런 다음 다음을 사용합니다.
    extract('https://www.google.com/search?q=devto');
    
    // Result:
    {
      host: "https://www.google.com",
      path: "/search?q=devto",
      subdomain: "www"
    }
    
    그러나 이것은 많지 않은 것 같다DRY.결과에 대한 연결과 부분에 대한 하드코딩 .google.com 이 필요 없이 정규 표현식에서 온전한 호스트를 직접 얻을 수 있을 것 같다.
    그래서 전체 호스트를 캡처하기 위해 다른 그룹을 추가했습니다.
    const regex = /(((https?:)?\/\/)?(.*)\.google\.com)(.*)/i;
    
    'https://www.google.com/search?q=devto'.match(regex);
    
    // Result:
    {
      0: "https://www.google.com/search?q=devto",
      1: "https://www.google.com",
      2: "https://",
      3: "https:",
      4: "www",
      5: "/search?q=devto",
      groups: undefined,
      index: 0,
      input: "https://www.google.com/search?q=devto",
      length: 6
    }
    
    아름답다이제 전체 호스트는 그룹 1, 하위 도메인은 그룹 4, 경로는 그룹 5로, 내 함수는 다음과 같이 단순화됩니다.
    function extract(url) {
      const regex = /(((https?:)?\/\/)?(.*)\.google\.com)(.*)/i;
    
      const match = url.match(regex);
    
      let result = {};
      if (match !== null) {
        result = {
          host: match[1],
          subdomain: match[4],
          path: match[5]
        };
      }
    
      return result;
    }
    
    지금까지 줄곧 괜찮았어!하지만 자세히 보면 2조와 3조는 정말 필요 없어요.그것들의 존재는 단지 우리가 그것들 주위에서 양사를 사용하고 싶기 때문일 뿐이지만, 우리는 그것들의 값을 단독으로 얻는 것에 대해 조금도 흥미를 느끼지 않는다.기본적으로 모든 그룹을 캡처하기 때문입니다.
    그리고 저는 여기서 dev.to에 대해 연구를 했는데 이 좋은 글을 발견했습니다.


    이제 나는 모든 그룹을 비포획조로 전환할 수 있다는 것을 알게 되었다. 단지 그 앞에 .google.com!감사합니다.
    !
    이제 2조와 3조가 잡히지 않도록 하겠습니다.
    const regex = /((?:(?:https?:)?\/\/)?(.*)\.google\.com)(.*)/i;
    
    'https://www.google.com/search?q=devto'.match(regex);
    
    // Result:
    {
      0: "https://www.google.com/search?q=devto",
      1: "https://www.google.com",
      2: "www",
      3: "/search?q=devto",
      groups: undefined,
      index: 0,
      input: "https://www.google.com/search?q=devto",
      length: 4
    }
    
    봐라!이제 그룹 1을 전체 호스트로, 그룹 2를 하위 도메인으로, 그룹 3을 경로로 사용합니다.우리는 상응하는 함수?:를 다시 쓸 수 있다.
    하지만 그 전에 케이크 위의 설탕 크림을 만들어 봅시다!ES2018 도입named capture groups은 이제 각 그룹을 이름으로 참조할 수 있음을 의미합니다.문법은 각 그룹의 시작에 덧붙인다extract.
    따라서 이제 정규 표현식은 다음과 같이 실행됩니다.
    const regex = /(?<host>(?:(?:https?:)?\/\/)?(?<subdomain>.*)\.google\.com)(?<path>.*)/i;
    
    'https://www.google.com/search?q=devto'.match(regex);
    
    // Result:
    {
      0: "https://www.google.com/search?q=devto",
      1: "https://www.google.com",
      2: "www",
      3: "/search?q=devto",
      groups: {
        host: "https://www.google.com",
        path: "/search?q=devto",
        subdomain: "www"
      },
      index: 0,
      input: "https://www.google.com/search?q=devto",
      length: 4
    }
    
    마지막으로 우리의 ?<name> 함수는 좀 간단해졌다.
    function extract(url) {
      const regex = /(?<host>(?:(?:https?:)?\/\/)?(?<subdomain>.*)\.google\.com)(?<path>.*)/i;
    
      const match = url.match(regex);
    
      return match !== null? match.groups: {};
    }
    

    DISCLAIMER: the concept of "simpler" here can be subjective. Typically, there is a trade-off between regex complexity and code complexity. In this case, we are writing a more complex regex to favor less complex code.

    Long story short, my recommendation is so you don't take this way too seriously and use your best judgment to never go too extreme. Remember: you write code for humans, which will have to maintain it even after you are gone. Thus, it doesn't really help much if you have the most elegant code ever written with the most complex regex ever.


    명명된 포획 그룹을 사용하면 BackreferencesReplacement targets 에서 더 많은 작업을 할 수 있습니다.
    역인용은 또 다른 괴물이다. 나는 다음 글에서 이 점을 소개할 계획이다.하지만 대상을 바꾸는 것은 더 간단합니다. 포획 그룹을 명명했을 때 문자열 extract 함수의 대상에서 사용할 수 있음을 의미합니다.구문은 대상 문자열에서 사용됩니다 replace.
    예를 들어, 대체된 문자열에서 캡처 $<name> 를 사용합니다.
    const regex = /(?<host>(?:(?:https?:)?\/\/)?(?<subdomain>.*)\.google\.com)(?<path>.*)/i;
    
    'https://www.google.com/search?q=devto'.replace(regex, 'subdomain: $<subdomain>');
    
    // Result
    'subdomain: www'
    
    그렇습니다, 점원들!나는 네가 매우 사람을 진작시키는 하루를 쉬기를 바란다.

    좋은 웹페이지 즐겨찾기