기본 콘텐츠로 건너뛰기

추천 가젯

[프로그래밍 이야기 6] 포터블 라이터기의 재발견: 웹소켓과 스크립트가 만든 현장 대응 파이프라인

 임베디드 장비나 FPGA 칩이 탑재된 하드웨어를 현장에서 다룰 때, 가장 고민스러운 부분은 펌웨어 라이팅 환경을 구축하는 일입니다. 공장 PC나 현장 컴퓨터에 무겁고 거대한 벤더 전용 프로그램(IDE)을 일일이 설치하고 환경을 설정하는 것은 지극히 비효율적입니다. 이때 가장 똑똑하고 유연한 접근법은 공장 PC에 무언가를 설치하려 애쓰는 대신, 엔지니어의 노트북 한 대를 즉시 '포터블(Portable) 라이터기'로 탈바꿈시켜 현장에 투입하는 것입니다. 노트북을 포터블 라이터기로 만드는 전략과 웹소켓 노트북을 이동식 포터블 라이터기로 활용하기 위해 거창한 프로그램을 깔 필요는 전혀 없습니다. 핵심은 펌웨어를 입히는 CLI(명령줄 인터페이스) 툴과, 이를 원격에서 실행해 줄 지극히 단순하고 가벼운 웹소켓(WebSocket) 서버 하나만 준비하는 것입니다. 중요한 점은 여기서 사용하는 웹소켓 프로그램이라는 것이 결코 복잡하거나 무거운 시스템이 아니라는 사실입니다. 단 몇 킬로바이트 수준의 경량 훅(Hook) 역할만 수행하는 웹소켓 서버를 노트북에 띄워두면, 공장 PC 환경을 오염시키지 않고도 노트북 한 대가 완벽한 이동식 라이팅 단말기로 변신합니다. 가장 가벼운 웹소켓 훅과 Shell 스크립트의 결합 이 시스템의 실체는 놀라울 정도로 가볍고 명확합니다. 노트북 내부에서는 하드웨어(.sof)를 구운 뒤 MCU 펌웨어(.elf)를 연달아 다운로드하는 아래의 Shell 스크립트가 실행의 중심을 잡습니다. // flasher.sh - FPGA 및 Nios II 펌웨어 연속 라이팅 스크립트 #!/bin/bash 1. FPGA Hardware (.sof) 구우기 #!/bin/bash echo "Hello World" echo "=== Programming FPGA Hardware ===" quartus_pgm -c "USB-Blaster [1-4]" -m JTAG -o "p;mcu.sof...

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 으로 쓰니까 같이 알아두자. 


댓글