이 블로그 검색

2018년 11월 16일 금요일

Vim 정규표현식 패턴 이해하기.

패턴. (help pattern 하면 나오는 부분에 대한 해설을 할거다. )


2. The definition of a pattern 패턴의 정의.
초짜는 help usr_27.txt를 찾아보시라 :help usr_27.txt라고 하면 됨.



1. 패턴은 가지의 or 연산 결과를 합한다.
  (한국말로 여러가지패턴을 찾을 수 있다.
  사실 패턴간 연산 순서를 말하는건데 concat이니 branch니 이래서 어려움)

pattern ::= branchA \| branchB \|branchC

A를 만족하거나 B를 만족하거나 C를 만족하거나.

예 이철수 \| 김철수 \| 박철수
라고 하면 이철수 또는 김철수 또는 박철수를 말한다.

2. 접붙이기 (And연산) 이다.  (concat이 식물학에서 뭘 의미하는건가?)
이 번에는 순서가 중요하다.
  branch ::=       concat
               or  concat \& concat
               or  concat \& concat \& concat

foobeep\&...   -> 을 해석하면 foobeep이라는 글자에서 foo 글자를 말한다 .
.*Peter\&.*Bob 는 Peter와 Bob을 모두 포함하는 Line 을 가리킨다.

첫번째 검색은 줄 전체를 검색해서 모든 문자열에서 Peter로 끝나는 문자열을 가리킨다. vim help 문서내에서 테스트 해볼 수 있다.

그 다음, 그 문자열을  다시 두번째 concat으로 검색을 한다. 그러면 라인처음에서 Peter 사이에 Bob로 끝나는 문자열을 내뱉는다.

   sjdklfjaslkj Peter klsjdlkfjs Bob kjdsklfjskdljfkl Peter    -- Matched
   lkjdslfkjsdlkjflk Peter lksdjflkjs Bob sdjflksjdlf klsdjflksj -- Not matched

상당히 요상하다.  Peter와 Bob가 모두 포함된 라인은 다음처럼 검색하면 된다.   .*Peter.*\&.*Bob.*
 Peter가 포함된 줄의 Bob만 찾는 다면 .*Peter.*\&Bob이다.

이 패턴이 찾기에 사용될 때는 커서의 위치가 패턴의 시작으로 가므로 중요할 수 있고,  찾아바꾸기에 사용될 때는 패턴의 끝도 중요해진다.

3. concat은 여러 조각으로 이루어진다.
 이미 쓰고 있었다. foo는 f다음에 o가 오고 또 o가 오는 문자열을 말한다.
  f[0-9]b 이 것은 f다음에 0-9중 하나가 오고 b가 오는 문자열 패턴이다.

4. 조각은 한개의 atom 또는 atom의 시퀀스를 말한다.


 piece   ::=      atom
               or  atom  multi
 예)   a*    "" a aa aaa aaa aaaa 등등

5. atom은 한 문자 또는 패턴이다. (??)
  여기서 부터 재귀라는 것을 알 수 있다. 패턴을 정의하는데 패턴을 알아야하니까 사실 그냥 다 패턴이고, 패턴간 연산순서로 기억하자.  그냥 국어적 의미도 필요없고 각자가 생각하는 패턴이 왠만하면 잘 맞으니까 무시하자. 

그냥 글자를 ordinary-atom이라고 부른다고 한다. 뭐 유니코드 같은건 수바이트가 한개의 atom이니까 ascii문자를 의미하는건 아니니까 오해하지 말자.

\(pattern\) 괄호로 묶으면, 온전한 한개의 패턴이 atom이 된다.
v\(abc\)*z 는  vz -> vabcz -> vabcabcz 뭐 이런 것이 되겠지.

저 atom 과 multi를 정의하는거는 쉽게 공부할 수 있다.



3. Magic

  문자열 내에 문자가 문자그대로가 특수한 역할을 맡을 때가 있다 그것을 Magic이라고 한다.  문자열을 최대한 자연스럽게 표현할 것이냐, 아니면 패턴을 최대한 쉽게 타이핑할 것이냐를 어떻게 설정할 것인지 vim에서는 조절할 수 있다.

after:    \v       \m       \M       \V         matches                'magic' 'nomagic'          $        $        $        \$         matches end-of-line          .        .        \.       \.         matches any character
         *        *        \*       \*         any number of the previous atom
         ~        ~        \~       \~         latest substitute string
         ()       \(\)     \(\)     \(\)       grouping into an atom
         |        \|       \|       \|         separating alternatives
         \a       \a       \a       \a         alphabetic character          \\       \\       \\       \\         literal backslash          \.       \.       .        .          literal dot          \{       {        {        {          literal '{'          a        a        a        a          literal 'a'
설정을 해도 딱히 몇개 바뀌지는 않는다. magic을 어떻게 하는지가 패턴을 많이 쓰는 vim하고 perl이 좀 달라서 혼동스러운데, 그럴때는 그냥 명시적으로 해결해라. perl에도 magic 설정이 가능한지는 모르겠다.



          multi     'magic' 'nomagic'  matches of the preceding atom /star   *       \*      0 or more       as many as possible
/\+     \+      \+      1 or more       as many as possible (*)
/\=     \=      \=      0 or 1          as many as possible (*)
/\?     \?      \?      0 or 1          as many as possible (*)
정규표현식은 cmd 창에서 쓰는 ?*하고는 다르다. 그러나 훨씬 다양한 패턴이 가능하므로 숙지하자. 여기가 가장 기본이다. \+도 사실 잘 안쓰인다. 그냥 글자를 한번더 찍어서 표현하자 . a\+ -> aa* 어차피 타이핑수도 동일하다.
/\{     \{n,m}  \{n,m}  n to m          as many as possible (*)        \{n}    \{n}    n               exactly (*)
       \{n,}   \{n,}   at least n      as many as possible (*)        \{,m}   \{,m}   0 to m          as many as possible (*)        \{}     \{}     0 or more       as many as possible (same as *) (*)
  기억하기 어렵지않다. 요거는 보통 dvc10003.jpg 같이 이미지 파일의 자리수와 관련된 일을 할 때 많이 쓴다.
/\{-    \{-n,m} \{-n,m} n to m          as few as possible (*)        \{-n}   \{-n}   n               exactly (*)
       \{-n,}  \{-n,}  at least n      as few as possible (*)        \{-,m}  \{-,m}  0 to m          as few as possible (*)        \{-}    \{-}    0 or more       as few as possible (*)
   요거 중요하다. 그리고 유용하다. 위에 있는 친구들은 전부다 as many as possible이라서 
 아까 있던 Peter.*Bob이라는 글자 지우려다가 한줄 전체를 날리는 경우가 허다하다. 그럴 때는 u를 누르고 요거를 쓰면 된다. 
  정규표현식 지원해주는 프로그램중에 as few as possible 안되는 친구들도 있다. 구리다. 
                                                       E59

/\@>    \@>     \@>     1, like matching a whole pattern (*)
/\@=    \@=     \@=     nothing, requires a match /zero-width (*)
/\@!    \@!     \@!     nothing, requires NO match /zero-width (*)
/\@<=   \@<=    \@<=    nothing, requires a match behind /zero-width (*)
/\@<!   \@<!    \@<!    nothing, requires NO match behind /zero-width (*)
 이거 좀 재미있다.  \@>는 아직 잘 모르지만, 
\(a*\)ab를 검색하면, 저 그룹에 b앞에 a가 포함되도록 하는것인데, 패턴의 중복을 막는 방법이고, 일상적으로 볼 일이 없다. 

이 zero width는 검색은 하되 패턴에는 포함이 되지 않는 것을 말하는데, 찾아바꾸기나, syntax highlighting에 중요하다. 난 김철수를 박철수를 바꾸고 싶다. 뭐 이런 상황에 사용된다. 찾아바꾸기야 통째로 김철수를 찾아 박철수로 바꾸면 되지만 김씨인 철수만 글자를 밝게 처리한다거나는 어려우니 이런기능이 필요하다. 

이 친구들은 위치가 중요한게 아니라 저거 앞에 있는 atom을 수식해주는 것이라 위치를 잘 파악하자.  김철수에 김을 수식할 때는, 김\(철수\)\@= 로 써야해서 좀 해깔릴 수 있으나 그냥 * 같은거라고 생각해야한다.

      ordinary atom      magic   nomagic   matches /^      ^       ^       start-of-line (at start of pattern) /zero-width /\^     \^      \^      literal '^'
/\_^    \_^     \_^     start-of-line (used anywhere) /zero-width /$      $       $       end-of-line (at end of pattern) /zero-width /\$     \$      \$      literal '$'
/\_$    \_$     \_$     end-of-line (used anywhere) /zero-width /.      .       \.      any single character (not an end-of-line)
/\_.    \_.     \_.     any single character or end-of-line
/\<     \<      \<      beginning of a word /zero-width /\>     \>      \>      end of a word /zero-width /\zs    \zs     \zs     anything, sets start of match
/\ze    \ze     \ze     anything, sets end of match
/\%^    \%^     \%^     beginning of file /zero-width           E71 /\%$    \%$     \%$     end of file /zero-width /\%V    \%V     \%V     inside Visual area /zero-width /\%#    \%#     \%#     cursor position /zero-width /\%'m   \%'m    \%'m    mark m position /zero-width /\%l    \%23l   \%23l   in line 23 /zero-width /\%c    \%23c   \%23c   in column 23 /zero-width /\%v    \%23v   \%23v   in virtual column 23 /zero-width
underbar는 잘 써본적이 없고, 보통 줄의 시작과 줄의 끝을 많이 사용한다. 그리고 c언어 등에서 value이름을 바꿀 때 \< \>를 많이 사용한다. 중복되는 부분들이 많아서 이거 생각없이 쓰면 100%에러가 난다. 
int x; 어쩌고 저쪼고 를 복사해서 int y 에 대해서 똑같이 하고 싶다고 복사한다음에 x를 y로 바꾸면 와장창 에러가 뜬다. \로 쓰면 된다.


Character classes {not in Vi}:                          /character-classes      magic   nomagic   matches /\i     \i      \i      identifier character (see 'isident' option) /\I     \I      \I      like "\i", but excluding digits
/\k     \k      \k      keyword character (see 'iskeyword' option)
/\K     \K      \K      like "\k", but excluding digits
/\f     \f      \f      file name character (see 'isfname' option)
/\F     \F      \F      like "\f", but excluding digits
/\p     \p      \p      printable character (see 'isprint' option)
/\P     \P      \P      like "\p", but excluding digits
/\s     \s      \s      whitespace character: and
/\S     \S      \S      non-whitespace character; opposite of \s
/\d     \d      \d      digit:                          [0-9] /\D     \D      \D      non-digit:                      [^0-9] /\x     \x      \x      hex digit:                      [0-9A-Fa-f] /\X     \X      \X      non-hex digit:                  [^0-9A-Fa-f] /\o     \o      \o      octal digit:                    [0-7] /\O     \O      \O      non-octal digit:                [^0-7] /\w     \w      \w      word character:                 [0-9A-Za-z_] /\W     \W      \W      non-word character:             [^0-9A-Za-z_] /\h     \h      \h      head of word character:         [A-Za-z_] /\H     \H      \H      non-head of word character:     [^A-Za-z_] /\a     \a      \a      alphabetic character:           [A-Za-z] /\A     \A      \A      non-alphabetic character:       [^A-Za-z] /\l     \l      \l      lowercase character:            [a-z] /\L     \L      \L      non-lowercase character:        [^a-z] /\u     \u      \u      uppercase character:            [A-Z] /\U     \U      \U      non-uppercase character         [^A-Z] /\_     \_x     \_x     where x is any of the characters above: character
                       class with end-of-line included


\s를 많이 쓰고 의외로 아래 digit류는 기억이 잘 안나서 오른쪽에 대괄호 형식으로, 풀어서 많이 쓰게 된다. 딱봐도 소문자랑 숫자 섞인것 같은거는 정의 안 되어 있다. 


      magic   nomagic   matches /\e     \e      \e       /\t     \t      \t       /\r     \r      \r       /\b     \b      \b       /\n     \n      \n      end-of-line
/~      ~       \~      last given substitute string
/\1     \1      \1      same string as matched by first \(\) {not in Vi} /\2     \2      \2      Like "\1", but uses second \(\)           ...
/\9     \9      \9      Like "\1", but uses ninth \(\)                                                                E68 /\z1    \z1     \z1     only for syntax highlighting, see :syn-ext-match           ...
/\z1    \z9     \z9     only for syntax highlighting, see :syn-ext-match
       x       x       a character with no special meaning matches itself

/[]     []      \[]     any character specified inside the []
/\%[]   \%[]    \%[]    a sequence of optionally matched atoms

/\c     \c      \c      ignore case, do not use the 'ignorecase' option
/\C     \C      \C      match case, do not use the 'ignorecase' option
/\Z     \Z      \Z      ignore differences in Unicode "combining characters".
                       Useful when searching voweled Hebrew or Arabic text.

\e는 고급사용자면 많이 쓸거다. \1 \9는 a-b를 b-a로 바꾼다거나 할 때 많이 쓴다.  vi에는 \( \) 없다고 한다, 얼마나 힘들겠는가... 그런데 vi에 메뉴얼의 패턴은 정의가 재귀적으로는 되어 있지 않겠다. 

\c는 최근에 쓰기 시작했다. grep은 -i 옵션 find -iname 으로 쓰니까 같이 알아두자. 


댓글 없음:

댓글 쓰기

가장 많이 본 글