Main Content

정규 표현식의 토큰

소개

정규 표현식에 사용되는 괄호는 표현식의 요소를 그룹화할 뿐만 아니라 해당 그룹에서 검색되는 모든 일치 항목을 토큰으로 지정합니다. 토큰을 사용하여 동일한 텍스트의 다른 부분을 일치시킬 수 있습니다. 토큰을 사용하면서 얻게 되는 이점 중 하나는 일치하는 항목을 기억하여 검색 또는 대체 과정에서 일치하는 텍스트를 다시 불러와서 재사용할 수 있다는 점입니다.

표현식의 각 토큰은 1부터 시작하여 왼쪽에서 오른쪽으로 진행되는 숫자로 할당됩니다. 표현식의 뒷부분에서 토큰을 참조하려면 토큰 번호 앞에 백슬래시를 사용하여 이를 참조하십시오. 예를 들어, 표현식에서 세 번째 괄호 세트로 생성되는 토큰을 참조하려면 \3을 사용하십시오.

단순한 예로, 문자형 배열에서 동일한 문자가 연이어 나오는 경우를 검색하려면 첫 번째 문자를 토큰으로 캡처한 후, 바로 다음에 오는 일치하는 문자를 검색하면 됩니다. 아래에 나와 있는 표현식에서 (\S) 구는 regexp가 문자형 배열에서 공백이 아닌 문자와 일치하는 항목을 찾을 때마다 토큰을 생성합니다. 표현식의 두 번째 부분인 '\1'은 첫 번째 항목 바로 다음에 동일한 문자가 두 번째로 나오는 경우를 찾습니다.

poe = ['While I nodded, nearly napping, ' ...
       'suddenly there came a tapping,'];

[mat,tok,ext] = regexp(poe, '(\S)\1', 'match', ...
               'tokens', 'tokenExtents');
mat
mat =

  1×4 cell array

    {'dd'}    {'pp'}    {'dd'}    {'pp'}

셀형 배열 tok에는 각각 토큰을 포함하는 셀형 배열이 있습니다.

tok{:}
ans =

  1×1 cell array

    {'d'}


ans =

  1×1 cell array

    {'p'}


ans =

  1×1 cell array

    {'d'}


ans =

  1×1 cell array

    {'p'}

셀형 배열 ext에는 각각 토큰에 대한 시작 인덱스와 끝 인덱스를 포함하는 숫자형 배열이 있습니다.

ext{:}
ans =

    11    11


ans =

    26    26


ans =

    35    35


ans =

    57    57

또 다른 예로, 일치하는 HTML 태그(예: <a></a>)와 태그 사이의 텍스트를 쌍으로 캡처하겠습니다. 이 예제에서 사용되는 표현식은 다음과 같습니다.

expr = '<(\w+).*?>.*?</\1>';

표현식의 첫 번째 부분인 '<(\w+)'는 여는 꺽쇠괄호(<)와 하나 이상의 영문자, 숫자 또는 밑줄 문자가 오는 문자열과 일치합니다. 묶는 괄호는 여는 꺽쇠괄호 다음에 오는 토큰 문자를 캡처합니다.

표현식의 두 번째 부분인 '.*?>.*?'는 이 HTML 태그의 나머지 부분(>까지의 문자)에서 다음 여는 꺽쇠괄호 앞까지의 모든 문자와 일치합니다.

마지막 부분인 '</\1>'은 닫는 HTML 태그에 포함된 모든 문자와 일치합니다. 이 태그는 연속된 문자 </tag>로 구성되며, 여기서 tag는 토큰으로 캡처된 모든 문자입니다.

hstr = '<!comment><a name="752507"></a><b>Default</b><br>';
expr = '<(\w+).*?>.*?</\1>';

[mat,tok] = regexp(hstr, expr, 'match', 'tokens');
mat{:}
ans =

    '<a name="752507"></a>'


ans =

    '<b>Default</b>'
tok{:}
ans =

  1×1 cell array

    {'a'}


ans =

  1×1 cell array

    {'b'}

여러 토큰

아래에는 토큰에 값이 할당되는 방법을 보여주는 예제가 나와 있습니다. 다음 텍스트를 검색한다고 가정하겠습니다.

andy ted bob jim andrew andy ted mark

다음 검색 패턴을 사용하여 위에 표시된 텍스트를 검색하도록 선택합니다.

and(y|rew)|(t)e(d)

이 패턴에는 토큰을 생성하는 세 개의 구문 표현식이 있습니다. 최종적으로 검색을 수행할 때 각 일치 항목에 대해 다음과 같은 토큰이 생성됩니다.

일치 항목

토큰 1

토큰 2

andy

y

 

ted

t

d

andrew

rew

 

andy

y

 

ted

t

d

최상위 괄호만 사용됩니다. 예를 들어, 검색 패턴 and(y|rew)가 텍스트 andrew를 찾은 경우 토큰 1에는 값 rew가 할당됩니다. 그러나, 검색 패턴 (and(y|rew))가 사용되는 경우 토큰 1에는 값 andrew가 할당됩니다.

일치하지 않는 토큰

검토하는 텍스트 내에 일치 항목이 없는 정규 표현식 내 토큰의 경우, regexpregexpi는 토큰 출력값으로 빈 문자형 벡터('')를 반환하고, 문자열에서 토큰이 예상된 위치를 표시하는 범위를 반환합니다.

여기에 나와 있는 예제에서는 MATLAB® tempdir 함수에서 반환되는 경로를 지정하는 문자형 벡터에 대해 regexp를 실행합니다. 정규 표현식 expr은 6개 토큰 지정자를 포함하는데, 각각의 토큰 지정자는 경로의 일부를 나타냅니다. 세 번째 지정자 [a-z]+의 경우 이 경로 부분 Profiles가 대문자로 시작하므로 문자형 벡터에서 이 지정자와 일치하는 항목이 없습니다.

chr = tempdir
chr =

    'C:\WINNT\Profiles\bpascal\LOCALS~1\Temp\'
expr = ['([A-Z]:)\\(WINNT)\\([a-z]+)?.*\\' ...
        '([a-z]+)\\([A-Z]+~\d)\\(Temp)\\'];

[tok, ext] = regexp(chr, expr, 'tokens', 'tokenExtents');

텍스트에서 토큰을 찾지 못하는 경우 regexp는 빈 문자형 벡터('')를 토큰으로 반환하고 토큰 범위가 포함된 숫자형 배열을 반환합니다. 범위(Extent)의 첫 번째 숫자는 토큰이 예상된 위치를 표시하는 문자열 인덱스이고, 범위의 두 번째 숫자는 첫 번째 숫자보다 하나 작습니다.

이 예제의 경우, 빈 토큰은 표현식에 지정된 세 번째 토큰이므로 반환되는 세 번째 토큰은 비어 있습니다.

tok{:}
ans =

  1×6 cell array

    {'C:'}    {'WINNT'}    {0×0 char}    {'bpascal'}    {'LOCALS~1'}    {'Temp'}

변수 ext에 반환되는 세 번째 토큰 범위는 시작 인덱스가 10으로 설정되어 있습니다. 여기서 10은 경로 내의 일치하지 않는 용어 Profiles가 시작되는 위치입니다. 범위의 끝 인덱스는 시작 인덱스보다 하나가 작은 9로 설정됩니다.

ext{:}
ans =

     1     2
     4     8
    10     9
    19    25
    27    34
    36    39

대체 텍스트의 토큰

대체 텍스트에 토큰을 사용할 경우 \1, \2 등을 사용하는 대신 $1, $2 등을 사용하여 이러한 토큰을 참조합니다. 이 예제에서는 두 개의 토큰을 캡처하고 토큰의 순서를 역순으로 뒤집습니다. 첫 번째 $1'Norma Jean'이며 두 번째 $2'Baker'입니다. 참고로, regexprep는 시작 인덱스로 구성된 벡터가 아니라 바뀐 텍스트를 반환합니다.

regexprep('Norma Jean Baker', '(\w+\s\w+)\s(\w+)', '$2, $1')
ans =

    'Baker, Norma Jean'

이름으로 캡처하기

표현식에 토큰을 많이 사용할 경우, 토큰에 할당된 토큰 번호를 추적할 필요 없이 이름을 할당하면 유용할 수 있습니다.

표현식 내에서 이름이 지명된 토큰을 참조할 때는 숫자형 \1, \2 등을 사용하는 대신 구문 \k<name>을 사용해야 합니다.

poe = ['While I nodded, nearly napping, ' ...
       'suddenly there came a tapping,'];

regexp(poe, '(?<anychar>.)\k<anychar>', 'match')
ans =

  1×4 cell array

    {'dd'}    {'pp'}    {'dd'}    {'pp'}

이름이 지명된 토큰은 MATLAB 정규 표현식 함수에서 반환되는 출력값에 레이블을 지정할 때도 유용할 수 있습니다. 많은 텍스트 조각을 처리하는 경우에 특히 유용합니다.

예를 들어, 여러 개의 문자형 벡터에서 도로명 주소의 서로 다른 여러 부분을 구문 분석해 보겠습니다. 표현식에서 각 토큰에 짧은 이름이 할당됩니다.

chr1 = '134 Main Street, Boulder, CO, 14923';
chr2 = '26 Walnut Road, Topeka, KA, 25384';
chr3 = '847 Industrial Drive, Elizabeth, NJ, 73548';

p1 = '(?<adrs>\d+\s\S+\s(Road|Street|Avenue|Drive))';
p2 = '(?<city>[A-Z][a-z]+)';
p3 = '(?<state>[A-Z]{2})';
p4 = '(?<zip>\d{5})';

expr = [p1 ', ' p2 ', ' p3 ', ' p4];

다음 결과에서 볼 수 있듯이, 명명된 토큰을 사용하면 출력값을 쉽게 활용할 수 있습니다.

loc1 = regexp(chr1, expr, 'names')
loc1 = 

  struct with fields:

     adrs: '134 Main Street'
     city: 'Boulder'
    state: 'CO'
      zip: '14923'
loc2 = regexp(chr2, expr, 'names')
loc2 = 

  struct with fields:

     adrs: '26 Walnut Road'
     city: 'Topeka'
    state: 'KA'
      zip: '25384'
loc3 = regexp(chr3, expr, 'names')
loc3 = 

  struct with fields:

     adrs: '847 Industrial Drive'
     city: 'Elizabeth'
    state: 'NJ'
      zip: '73548'

참고 항목

| |

관련 항목