gema : 텍스트변환도구중 내가 본것중에 최고.

임창진의 이미지

gema : 텍스트변환도구중 내가 본것중에 최고.
홈페이지는 http://gema.sourceforge.net 여기.

http://smallbasic.sourceforge.net/index.php#download 에 가셔서 gemapad(ms-windows용)를 받아서 설치하시기 바랍니다.
뒤에나올 예제들을 따라하는데 많은 도움이 될 것입니다.
!!주의 : 설치디렉토리가 Program files 처럼 공백을 포함한곳이면 정상작동을 하지않습니다. 간으하면 디렉토리 path 에 공백이나 한글이 포함되지않은 곳에 설치하시기 바랍니다.
http://www.anthus.com/Gema/WhyILoveGema.html <= 여기서 표를 보시기 바랍니다.
http://gema.wiki.sourceforge.net/WhyILoveGema 위 링크가 죽었습니다. 이쪽으로 가보세요
저의경우 이표를 보고 이게 정말 이렇게 좋단 말인가? 하고 호기심이 생겨 gema를 익히게 되었습니다.

gema 의 commad line option 은 위에 링크된 홈페이지의 문서를 참고하시고 gemapad 를 설치했다고 가정하고
예제중심으로 gema pattern을 어떻게 기술하는지 살펴보기로 하겠습니다.

우선 gemapad 를 실행시키면 4개의 tab 이 보입니다.
source ,gema, output ,help 이렇게 4개
예제의 구성은 아래처럼 source,gema,output 3개를 표시할겁니다.
gemapad에 복ㅤㅅㅏㅎ서 붙여넣어서 테스트 해보시기 바랍니다.
(외따옴표로 둘러싸인 부분은 복사해서붙여넣는게 아니란걸 말 안해도 다 아시겠지만,꼭 붙여놓고 안된다고 하는 분이 있습니다.)

'source----------'
aaaaaa
'gema------------'
a=A
'output----------'
AAAAAA
'----------------'

서론이 길었죠. 이제부터 설명을 하는데 제가 프로그래머로 10년가까이 일했지만 아직 독타라서 게다가 한타가 영타보다 더 느리고 해서
한/영키를 최대한 안누르는 방향으로 타이핑 할겁니다. 이해해주시기 바랍니다.

제마 패턴의 구조

[find]=[replace]
[find1]=[replace1]
[find2]=[replace2]
[find3]=[replace3]
.
.
.

'=' 를 중심으로
왼쪽에는 '찾을문자열' 또는 '정규식 또는 gema의 recognizer 을 조합한 패턴'
오른쪽에는 찾은 문자열을 대체할 '무엇'을 기술한다.
패턴적용순서는 긴패턴을 먼저 적용합니다.

예1 ) source 에 나타나는 모든 a 를 A 로 비꾼다.

'source----------'
aaaaaa
'gema------------'
a=A
'output----------'
AAAAAA
'----------------'

예2) source 에 나타나는 모든 a 를 A 로 바꾸고 b 는 B 로 바꾼다.

'source----------'
aaa
bbb
'gema------------'
a=A
b=B
'output----------'
AAA
BBB
'----------------'

예3) source 에 나타나는 모든 a 를 A 로 바꾸고 aa 는 [AA] 로 바꾼다

'source----------'
aaaaa
'gema------------'
aa=[AA]
a=A
'output----------'
[AA][AA]A
'----------------'

실습 : gema 패턴의 순서를 아래와 같이 바꾸고 어떤 결과가 나올지 생각해보라

a=A
aa=[AA]

예4) source 에 나타나는 모든 연속된 2개의 알파벳을 []로 둘러싼다.(정규식이용)

'source----------'
abc defg hijklmn
opqr stu
'gema------------'
/[a-zA-Z][a-zA-Z]/=[$1]
'output----------'
[ab]c [de][fg] [hi][jk][lm]n
[op][qr] [st]u
'----------------'

자습 : $1 이 뭘 뜻하는지 짐작할수없는분은 홈페이지의 메뉴얼을 읽어보기 바란다.

예5) source 에 나타나는 모든 연속된 2개의 알파벳을 []로 둘러싼다.(recognizer 이용 )

'source----------'
abc defg hijklmn
opqr stu
'gema------------'
<L2>=[$1]
'output----------'
[ab]c [de][fg] [hi][jk][lm]n
[op][qr] [st]u
'----------------'

자습 : <L> 말고도 recognizer는 많다 저는 영어독해를 그리 정밀하게 하는편은 아니어서
리코그나이저의 용도를 어떻게 배웠냐하면 일단 제마패드의 source 부분에 아무 텍스트나 복사해 넣고
gema 패턴에다가 <A>=[$1] 이렇게 해놓고 돌려보면 어떤 스트링에 [] 표가 둘러 쳐지는지 볼수 있었고
그렇게 리코그나이저 배웠다.

예6)외따옴표를 쌍따옴표로 바구어라 단 \' 이렇게 표시된 외따옴표는 그대로 둔다.

'source----------'
print 'abcde fg\'ijk lmn';
print 'it\'s so easy';
'gema------------'
\\'=$0
'="
'output----------'
print "abcde fg\'ijk lmn";
print "it\'s so easy";
'----------------'

설명
$0 은 $1,$2,$3... 들과 달리 '=' 왼편에 기술된 패턴에의해 검색된 스트링 그자체가 들어간다.
\ 는 escape 문자다.

예7) 대소문자를 가리지 말고 a 는 그대로 남기고 나머지는 모두 스페이스로 바꾼다(개행문자는 그대로 놔둔다).

'source----------'
print 'Abcde fg\'ijk lmna';
print 'it\'s so easy';
'gema------------'
a=a
A=A
\n=\n
\r=\r
<U1>=\s
'output----------'
       A                a
                 a
'----------------'

예8) java 소스코드의 주석을 모두 제거한다.


'source----------'
/**
 * @author callin
 *         <p/>
 *         //* @deprecated AntZipUtil 을 사용하시오
 */
public class ZipUtil
{

    /**
     * 인풋스트림의 내용을 아웃풋스트림으로 복사한다.
     *
     * @param in
     * @param out
     *
     * @throws IOException
     * @author callin
     * @since JDK 1.4.1.05
     */
    public static void copyInputStream(InputStream in, OutputStream out) throws IOException
    {

        if (in == null)
        {
            if (out != null)
            {
                out.close();
            }
            return;
        }

        //byte[] buffer = new byte[4096];
        //int len;

        while ((len = in.read(buffer)) >= 0)
        {
            out.write(buffer, 0, len);  // comment
        }

        in.close();
        out.close();

    }
'gema------------'
\/\*<U>\*\/=
\L\/\/<U>=
\L"<QS>"=$0

QS:\\\\=$0
QS:\\"=$0
QS:"=@fail{}
'output----------'

public class ZipUtil
{


    public static void copyInputStream(InputStream in, OutputStream out) throws IOException
    {

        if (in == null)
        {
            if (out != null)
            {
                out.close();
            }
            return;
        }




        while ((len = in.read(buffer)) >= 0)
        {
            out.write(buffer, 0, len);
        }

        in.close();
        out.close();

    }
'----------------'

설명
이 예제에서 보인 제마패턴이 언뜻보기엔 난수표 같아 보이지만 알고보면 단순하다.
제마에서 / \ * < > 들은(이 이외에도 더 있지만) 특별하게 취급되는 문자이다 그렇기 때문에 문자자체의 의미만을 주기위해서
\ 를 앞에 붙여야한다.
\를 떼어내고 보면 위 패턴은

/*<U>*/=
\L//<U>=

이것이고 \L 이 라인모드라는거만 빼놓으면 의미는 아주 간단하다. '=' 의 오른쪽에 아무것도 없는경우는 패턴에 매칭된 문자열을
삭제하란 뜻이다.

---------------
오늘은 여기까지입니다.
그간 여기서 다른분들이 올린 여러가지 유용한 문서들을 고마운줄 모르고 많이 봐왔습니다.
오늘 이렇게 몇줄안되는 걸 적으려해도 귀찮고 힘들었습니다.
그래서 여지껏 그많은 문서들을 만들고 정리하신 분들게 정말 감사한 마음이 듭니다.

부디 gema 가 여러분의 삶을 좀더 편하게 해주었으면 합니다.
반응이 뜨거우면 :D gema에서 domain(사용자 정의함수/recognizer)의 사용법과 lua 와 연동 하는것도 해볼랍니다.

File attachments: 
첨부파일 크기
Package icon gel.zip69.14 KB
Forums: 
saxboy의 이미지

좋은 툴입니다만.... vi와 sed/awk/perl 을 써보신다면 좀 더 큰 감동을 받으실지도 모르겠습니다.

galien의 이미지

좋아보이는 군요.

함 사용해 보겠습니다.

eddy_woody의 이미지

saxboy wrote:
좋은 툴입니다만.... vi와 sed/awk/perl 을 써보신다면 좀 더 큰 감동을 받으실지도 모르겠습니다.

저도 gema를 막 써보려는 참입니다만,
프로젝트 홈페이지에 있는 소개글에 의하면
vi/perl/gema 조합이 더 강력할 듯 합니다. 8)

> It can take much longer than necessary to get rid of a problem professor...

I'm thinking duct tape and a trunk.

galien의 이미지

제가 gema에게 느낀 큰 매력은...

gemapad로 인해 보다 휴먼 리더블한 일을 할 수 있다는 건데요.

파워풀하기로 따지면 크게 매력적이진 않을 지 몰라도..

:wink:

랜덤여신의 이미지

Quote:
java 소스코드의 주석을 모두 제거한다.

이거, 정규식으로
/\*.*?\*/|//.*?$
정도로 끝나지 않을까요? ^^;
girneter의 이미지

김상욱 wrote:

gemapad로 인해 보다 휴먼 리더블한 일을 할 수 있다는 건데요.

파워풀하기로 따지면 크게 매력적이진 않을 지 몰라도..

네 제가 보기에도 그렇습니다

sed/awk/perl

이게 강력하다는것 알고 필요할때도 많아서
배워야겠다 생각은 하면서도
늘 인간매크로를 하곤하는데
위 친절한 소개글을 보니
웬지 접근하기가 좀더 가깝겠다는 *느낌*이 듭니다
깊이 들어가면 그거나 그거나겠지만 말이죠.

개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?

익명 사용자의 이미지

이거 저한테 정말 필요한 기능이라서 이런 문서가 정말 반갑습니다.
말씀하신 홈페이지에서 gemapad(ms-windows용)을 받은 다음 압축을 푸니 실행 파일이 있더군요. 실행시킨 후 source에서 제가 원하는 자바 소스 파일을 불러오고 gema에는 자바 주석 제거하는
\/\*<U>\*\/=
\L\/\/<U>=
을 입력했습니다.

그리고 어떤 파일에 output가 될지 정한 뒤에 run을 시키니
C:\Documents: No such file or directory
Can't open file for reading:
라는 메시지만 나오네요...이리저리 해봐도 결과는 계속 마찬가지네요..
어떻게 해야할지..

tinywolf의 이미지

음.. 디렉토리 이름이나 파일이름에 공백이 들어갈 경우에는 따옴표로 묶어 주시면 됩니다. 아마 그 문제가 아닐지..

ㅡ_ㅡ;

ㅡ,.ㅡ;;의 이미지

저는 제가원하는걸 마땅히 못찾아서 제가만들어서 썻는데..ㅡ,.ㅡ;;;

혹시 이런경우 다른분들은 어떻게 사용하시는지..궁금..

예를들면

첫줄   : "abcdefg어쩌고 저쩌고 랄랄라"
둘째줄: "abcd잉g어쩌고      저쩌고 랄랄까"
둘째줄: "abcdxxg어쩌고     저쩌고 랄랄랄"

머이런식으로 둘째줄중간 에 몇칸떨어질지 의문이고..
'잉'자부분은 무슨글자가 나올지의문이고.. 랄랄라 와 랄랄까 만허용하고 랄랄랄은 허용하지 않는 패턴의문장을 특정문장으로 치환
혹은 저런패턴문장을 검색 하는걸 어떻게 하시나요?
또한 a 이거나 혹은 b이거나 혹은 c인것들을 동시에찾거나 대체할때..


----------------------------------------------------------------------------

임창진의 이미지

초보자 wrote:
이거 저한테 정말 필요한 기능이라서 이런 문서가 정말 반갑습니다.
말씀하신 홈페이지에서 gemapad(ms-windows용)을 받은 다음 압축을 푸니 실행 파일이 있더군요. 실행시킨 후 source에서 제가 원하는 자바 소스 파일을 불러오고 gema에는 자바 주석 제거하는
\/\*<U>\*\/=
\L\/\/<U>=
을 입력했습니다.

그리고 어떤 파일에 output가 될지 정한 뒤에 run을 시키니
C:\Documents: No such file or directory
Can't open file for reading:
라는 메시지만 나오네요...이리저리 해봐도 결과는 계속 마찬가지네요..
어떻게 해야할지..

gemapad 가 설치된 경로에 공백이포함된경우 인식을 하지 못하는거 같습니다.

임창진의 이미지

ㅡ,.ㅡ;; wrote:
저는 제가원하는걸 마땅히 못찾아서 제가만들어서 ㅤㅆㅓㅅ는데..ㅡ,.ㅡ;;;

혹시 이런경우 다른분들은 어떻게 사용하시는지..궁금..

예를들면

첫줄   : "abcdefg어쩌고 저쩌고 랄랄라"
둘째줄: "abcd잉g어쩌고      저쩌고 랄랄까"
둘째줄: "abcdxxg어쩌고     저쩌고 랄랄랄"

머이런식으로 둘째줄중간 에 몇칸떨어질지 의문이고..
'잉'자부분은 무슨글자가 나올지의문이고.. 랄랄라 와 랄랄까 만허용하고 랄랄랄은 허용하지 않는 패턴의문장을 특정문장으로 치환
혹은 저런패턴문장을 검색 하는걸 어떻게 하시나요?
또한 a 이거나 혹은 b이거나 혹은 c인것들을 동시에찾거나 대체할때..

\L<U>\: "abcd<U2>g어쩌고 저쩌고 <lala>"=[$0]
lala:랄랄까=$0@end{}
lala:랄랄라=$0@end{}
lala:=@fail{}

위 답변은 user define recognizer를 사용해서 풀어보았습니다.
lala 가 user define recognizer인데 제가 [2]에서 설명한 사용자정의 함수와의 차이점은 '=' 의 왼쪽에서 사용한다는 점이고 정의하는 부분은 사용자정의 함수와 다른것이 없습니다.

두번째 질문하신것도 user define recognizer를 응용하시면 보다 직관적으로 해결할수 있습니다.(user define recognizer 를 사용하지 않아도 해결됩니다)

'source-----------------'
A XXXXXXXXXXX
B XXXXXXXXXXX
C XXXXXXXXXXX
'gema -----------------'
<AorBorC>=[$1]


AorBorC:A=$0@end{}
AorBorC:B=$0@end{}
AorBorC:C=$0@end{}
AorBorC:=@fail{}
'output ------------------------'
[A] XXXXXXXXXXX
[B] XXXXXXXXXXX
[C] XXXXXXXXXXX
'------------------------------------'
서지훈의 이미지

근데... 이거 도배인가요 ㅡㅡㅋ

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

임창진의 이미지

서지훈 wrote:
근데... 이거 도배인가요 ㅡㅡㅋ

<어떠한 역경에도 굴하지 않는 '하양 지훈'>


도배라는 생각이 드신다니 그만 올리겠습니다.
서지훈의 이미지

새로운 툴을 소개 해주시고 방법까지 세세히 설명을 해주시니 고마울 따름입니다.
또 새로운거 하나를 배우게되니깐요.
그러나, 올리는 방법이 연관된 내용들을 쪼개서 올리시는것 보단 하나의 파일로 작성을 하셔서 올려 주시거나, 한 쓰레드에 연재를 하시거나, 위키 등에 올려 주시면 더 찾기도 쉽고 보기도 편하고 임창진님도 관리가 편하지 않을까 생각을합니다.
자료 한 번 정리 / 취합하셔서 올려 주시면 정말 요긴할것 같군요.

근데 이렇게 민감하게 반응을 보일실지 모르고 제가 한 말은 사과를 드리겠습니다.

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

ㅡ,.ㅡ;;의 이미지

임창진 wrote:

\L<U>\: "abcd<U2>g어쩌고 저쩌고 <lala>"=[$0]
lala:랄랄까=$0@end{}
lala:랄랄라=$0@end{}
lala:=@fail{}

위 답변은 user define recognizer를 사용해서 풀어보았습니다.
lala 가 user define recognizer인데 제가 [2]에서 설명한 사용자정의 함수와의 차이점은 '=' 의 왼쪽에서 사용한다는 점이고 정의하는 부분은 사용자정의 함수와 다른것이 없습니다.

어쩌고와 저쩌고 사이 가운데 불규칙적인길이의 문자가 포함되어 있는것은 해결안된듯하네요..


----------------------------------------------------------------------------

익명 사용자의 이미지

ㅡ,.ㅡ;; wrote:
임창진 wrote:

\L<U>\: "abcd<U2>g어쩌고 저쩌고 <lala>"=[$0]
lala:랄랄까=$0@end{}
lala:랄랄라=$0@end{}
lala:=@fail{}

위 답변은 user define recognizer를 사용해서 풀어보았습니다.
lala 가 user define recognizer인데 제가 [2]에서 설명한 사용자정의 함수와의 차이점은 '=' 의 왼쪽에서 사용한다는 점이고 정의하는 부분은 사용자정의 함수와 다른것이 없습니다.

어쩌고와 저쩌고 사이 가운데 불규칙적인길이의 문자가 포함되어 있는것은 해결안된듯하네요..

\L<U>\: "abcd<U2>g어쩌고<U>저쩌고 <lala>"=[$0]
lala:랄랄까=$0@end{}
lala:랄랄라=$0@end{}
lala:=@fail{}
죠커의 이미지

열정은 좋으신데 쓰래드 하나에 답변의 형태로 달았으면 더 좋지 않았을까요?
쓰래드 3개를 여신 것은 좀 에러 같습니다.

임창진의 이미지

예2-1) 정규식의 .* 와 recognizer <U> 의 차이점
따옴표로 둘러싸인 문자열을 []로 한번 더감싸기

'source----------'
"asdasd"   "adasdasda"
"asdasd
    sdfsdfsdf"
'gema------------'
/".*"/=[$1]
'output----------'
["asdasd"   "adasdasda"]
"asdasd
    sdfsdfsdf"
'----------------'

'source----------'
"asdasd"   "adasdasda"
"asdasd
    sdfsdfsdf"
'gema------------'
"<U>"=[$0]
'output----------'
["asdasd"]   ["adasdasda"]
["asdasd
    sdfsdfsdf"]
'----------------'

설명
gema 에서 정규식은 '/' 로 둘러싸서 그안에 정규식 표현을 쓰면 됩니다.
gema 는 특별히 line mode 라고 \L 로 지정하지 않으면 개행문자도 다른것들과 똑같이 취급합니다.
그래서 두번째의 경우 결과가 기대했던거랑 다르지요
그리고 첫번째 줄이 정규식이랑 recognizer랑 이용했을때 나온결과가 다릅니다.
보통의 경우 아래쪽처럼 변환하고 싶은데 정규식의 결과는 기대했던거랑 다릅니다.
저는 정규식에 익숙하지 않습니다. 아마도 정규식을 다르게쓰면 아래쪽처럼 변환할수 있을겁니다.
근데 여기서 제가 말하고 싶은것은 변환문법이 얼마나 단순하고 직관적이냐 하는 겁니다.

예2-2)사용자 정의 함수 (자바독형태의 주석에서 param 값만 떼어내어 표시한다.)

'source----------'
/**
* " 처리 샘플 입니다.
* @param p1
*/
hello( String p1 )	{
	//assign @param p1 to x
	String x = p1;
	print("hello world and \"hello korea\ " " + p1);
}
'gema------------'
\/\*<U>\*\/=@paramfilter{$1}
<U1>=

paramfilter:\@param <I>=[$1]
paramfilter:<U1>=
'output----------'
[p1]
'----------------'

조금 어려운 예제입니다.
사용자 정의 함수는 @함수명{파라미터} 형태로 되어있습니다.

함수의 정의는 gema 의 패턴정의와 같이 [find]=[replace] 형태로 기술하되 맨앞에 함수명:이 와야 합니다.
그러면 최종적으로
함수명:[find]=[replace] 로 기술하면 됩니다.
gema 의 패턴정의와 마찬가지로 먼저기술된걸 먼저 찾아서 바꿉니다.

아래 예제는 위의 gema 패턴과 한줄이 다릅니다 '<U1>=' 을 삭제했습니다.
그러나 결과는 같지요 왜냐ㅤㅁㅑㄴ 이걸 gemapad 에서 실행하기전에 matches only mode 를 켰기때문입니다.

'source----------'
/**
* " 처리 샘플 입니다.
* @param p1
*/
hello( String p1 )	{
	//assign @param p1 to x
	String x = p1;
	print("hello world and \"hello korea\ " " + p1);
}
'gema------------'
\/\*<U>\*\/=@paramfilter{$1}

paramfilter:\@param <I>=[$1]
paramfilter:<U1>=
'output----------'
[p1]
'----------------'

예2-3)look ahead
a-)b-)c-)d 형태의 문자열을

a-)b
b-)c
c-)d 형태로 바꿔라

'source----------'
aaa-)bb-)cxcd-)dfrg
'gema------------'
<L>-)\P<L>=$0\n
'output----------'
aaa-)bb
bb-)cxcd
cxcd-)dfrg
'----------------'

설명 : 위 예제는 matches only mode 를 켜고 실행해야 합니다.
\P 는 gema 다음 검색할때 시작 위치를 나타냅니다. 말이 너무 어렵죠
<L>-)\P<L> 에서 일단 \P를 빼고 <L>-)<L> 형태로 패턴을 찾아서 그런 형태가 나오면 변환을 하고
그다음 패턴을 적용하는거는 \P 로 설정된 위치부터 하는 겁니다. 설명하기 너무 어렵네요. 그래서~

숙제 : 새로배운 \P 를 이용해서 빈줄만(공백문자만 있는 행도 빈줄에 포함) 삭제하는 패턴을 만들어 보시오

'source----------'
a

bb



ccc

d
'gema------------'
숙제
'output----------'
a
bb
ccc
d
'----------------'

예2-4)recurisve argument '#'
lisp 스타일의 문장을 c 스타일로 바꾼다.
gemapad 의 matches only mode 끄세요

'source----------'
(a b c)
(d (e f g) h)
(a b (d (e f g) h))
'gema------------'
(# # #)=$1($2 $3)
'output----------'
a(b c)
d(e(f g) h)
a(b d(e(f g) h))
'----------------'

설명이 필요없죠? 끝내주죠? ^^

임창진의 이미지

user define recognizer를 좀더 살펴봅시다.
아래 예제는 어떤 프로그램에서 만들어낸 log 를 필터링 하는 예제입니다.
(물론 log 프로그램의 설정을 바구어 같은 결과를 얻을수 있습니다만 여기선 gema 의 설명이 목적입니다.)

'source ----------------------------'
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 1]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 2]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 3]
20050505 12-30-57 DEBUG com.xxx.yyy  [log mesg 4]
20050505 12-30-57 DEBUG com.xxx.yyy  [log mesg 5]
20050505 12-30-57 DEBUG com.xxx.yyy  [log mesg 6]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 7]
20050505 12-30-57 ERROR com.xxx.yyy  [log mesg 8]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 9]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 10]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 11]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 12]
20050505 12-30-57 FATAL com.xxx.yyy  [log mesg 13]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 14]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 15]
'gema ----------------------------'
<DTIME> <LEVEL> <LOGGER> <LOGMSG>=( $0 )

DTIME:<D8> <D2>-<D2>-<D2>=$0@end{}
DTIME:=@fail{}

LEVEL:DEBUG=$0@end{}
LEVEL:INFO=$0@end{}
LEVEL:WARN=$0@end{}
LEVEL:ERROR=$0@end{}
LEVEL:FATAL=$0@end{}
LEVEL:=@fail{}

LOGGER:<G>=$0@end{}
LOGGER:=@fail{}

LOGMSG:[<U>]=$0@end{}
LOGMSG:=@fail{}
'output ----------------------------'
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 1] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 2] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 3] )
( 20050505 12-30-57 DEBUG com.xxx.yyy [log mesg 4] )
( 20050505 12-30-57 DEBUG com.xxx.yyy [log mesg 5] )
( 20050505 12-30-57 DEBUG com.xxx.yyy [log mesg 6] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 7] )
( 20050505 12-30-57 ERROR com.xxx.yyy [log mesg 8] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 9] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 10] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 11] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 12] )
( 20050505 12-30-57 FATAL com.xxx.yyy [log mesg 13] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 14] )
( 20050505 12-30-57 INFO com.xxx.yyy [log mesg 15] )
' ----------------------------'

DTIME:<D8> <D2>-<D2>-<D2>=$0@end{}
DTIME:=@fail{}

<DTIME>의 경우
첫번째 정의에서는 날짜(숫자)8자리 시(숫자2)-분(숫자2)-초(숫자2) 의 패턴을 만나면 그걸 그대로 돌려주고
패턴검색을 거기에서 종료합니다.

gema 패턴의 아래부분을 $0 에서 $1 으로 바꾸어 놓고 결과를 확인해 보시기 바랍니다.
<DTIME> <LEVEL> <LOGGER> <LOGMSG>=( $0 )

다른 user define recognizer들도 비슷한 방법으로 패턴을 검색합니다.

<LOGGER> 는 @end{} 를 사용하지 않고 다른방법으로 구현될수 있습니다
@end{} 가없으면 gema 는 계속 다음 문자를 덧붙여서 패턴에 대입해봅니다.
설명을 잘 하기어려운데 패턴을 아래와 같이 바꾸고 해보시기 바랍니다.

LOGGER:<L>=$0
LOGGER:\.=$0

----------------------------------
위의 패턴으로 결과를 검색하였습니다.
이제 로그중에 INFO 로그만 보도록 gema 패턴을 수정합니다.
(물론 grep 을 쓰는게 제일 간단합니다만 이다음 예제는 grep 을 가지고 하기가 곤란합니다.)

gema 패턴의 첫번째 줄을 아래와 같이 수정하시기 바랍니다.

<DTIME> <LEVEL> <LOGGER> 
<LOGMSG>=@cmps{INFO;$2;;$0;}

@cmps 는 스트링을 비교하는 gema 내장 함수입니다. (자세한건 gemapad의 help tab에서...)

------------------------------------------------
이번엔 똑같이 로그중에 INFO 로그만 보도록 gema 패턴을 수정합니다.
다만 source 가 아래와 같이 바뀝니다.

'source ----------------------------'
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 1
msg cont.
msg cont.
msg cont.
msg cont.
]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 2
msg cont.
msg cont.
msg cont.
msg cont.
]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 3
msg cont.
msg cont.
msg cont.
msg cont.
]
20050505 12-30-57 DEBUG com.xxx.yyy  [log mesg 4
msg cont.
msg cont.
]
20050505 12-30-57 DEBUG com.xxx.yyy  [log mesg 5
msg cont.
msg cont.
msg cont.
]
20050505 12-30-57 DEBUG com.xxx.yyy  [log mesg 6]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 7]
20050505 12-30-57 ERROR com.xxx.yyy  [log mesg 8]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 9]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 10]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 11]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 12]
20050505 12-30-57 FATAL com.xxx.yyy  [log mesg 13]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 14]
20050505 12-30-57 INFO com.xxx.yyy  [log mesg 15]

위와같이 source 가 바뀌더라도 gema 패턴은 수정 할 필요 없습니다. 확인해 보세요..

-------------------------------------
이번엔 log 파일을 쭉스캔해서
log level 별로 다른 파일에 저장합니다.

gema 패턴의 첫번째 줄을 아래와 같이 수정하시기 바랍니다.

<DTIME> <LEVEL> <LOGGER> <LOGMSG>=@write{$2;$0\n}

실행한후 gemapad가 설치된 directory 에 어떤 파일이 생겼고 내용이 어떤가 확인해보시기 바랍니다.

끝.

익명 사용자의 이미지

아래의 gema rule 은 사칙연산('(',')' 포함)을 찾아주는 패턴입니다(아직 버그가 있습니다)
맨위 '!'로 시작하는 6줄은 주석입니다. BNF 스타일로 expr 의 정의를 보여줍니다
아래 gema 의 userdefine recognizer로 구현된것과 비교해 보면 상당히 비슷합니다.
gema 가 얼만큼 직관적으로 사용될수 있는지 볼수있는 좋은 예 입니다.
관련 link 입니다.
http://www.dentato.com/gel/zz/bnf.htm

!expr ::= term {op term} ;
!term ::= [sign] & fact;
!fact ::= '(' expr ')' | INT;
!op   ::= pm | '*' | '/';
!sign ::= pm ;
!pm   ::= '+' | '-';

\L<expr>=e[$0]

expr:<term>=$0@end
expr:<term>\W<_lst1>=$0@end
expr:=@fail{}

_lst1:<op>\W<term>=$0
_lst1:<S>=
_lst1:<_num>=@fail{}
_lst1:=@end


term:<_opt1><fact>= st[$0]@end
term:<fact>= t[$0]@end
term:=@fail{}

_opt1:<sign>=$0@end
_opt1:=@fail{}


fact:(\G\W<expr>\W)\G= pf[$0]@end
fact:<_num>=f[$0]@end
fact:=@fail{}

op:<pm>= op[$0]@end
op:\*\G= op[$0]@end
op:\/\G= op[$0]@end
op:=@fail{}

pm:+\G=$0@end
pm:-\G=$0@end
pm:=@fail{}

sign:<pm>=$0@end

_num:<N>=$0@end
_num:=@fail  
임창진의 이미지

사용자 정의 recognizer를 이용한 예제 한개더 입니다.
아래 gema rule 은 java source 코드로 부터 method 및 메쏘드가 시작되는 라인번호를 보여줍니다.

recognizer의 앞에 있는 주석은 해당 recognizer의 BNF 입니다.
gema 실행시 -match option 을 주고 실행하시기 바랍니다.

제가 위에올린글에포함된 링크를 따라가시면
BNF -> gema rule 으 변환방법이 상세하게설명되어 있습니다.

!http://cui.unige.ch/db-research/Enseignement/analyseinfo/JAVA/method_declaration.html

<method_declaration>=[  $0  ] \:@line{} \n

!method_declaration
!      ::=
!      { modifier } type identifier       "(" [ parameter_list ] ")" { "[" "]" }
!      ( statement_block | ";" )
method_declaration:<_optionalModifier> <type> <ID>\W(\W<_optionalParamList>\W)=$0@end{}
method_declaration:=@fail{}

_optionalModifier:<modifier>=$0
_optionalModifier:<S>=$0
_optionalModifier:=@end{}

_optionalParamList:<parameter_list>=$0@end{}
_optionalParamList:=@fail{}


!modifier
!      ::=
!      "public"       | "private"       | "protected"       | "static"       | "final"       | "native"       | "synchronized"       | "abstract"       | "threadsafe"       | "transient"
modifier:public=$0@end{}
modifier:private=$0@end{}
modifier:protected=$0@end{}
modifier:static=$0@end{}
modifier:final=$0@end{}
modifier:native=$0@end{}
modifier:synchronized=$0@end{}
modifier:abstract=$0@end{}
modifier:threadsafe=$0@end{}
modifier:transient=$0@end{}
modifier:=@fail{}

!type
!      ::=
!      type_specifier { "[" "]" }
type:<type_specifier><_optionalBR>=$0@end{}
type:=@fail{}

_optionalBR:[\W]=$0@end{}
_optionalBR:<S>=
_optionalBR:=@end{}

!parameter_list
!      ::=
!      parameter { "," parameter }
parameter_list:<parameter><_optionalPARAM>=$0@end{}
parameter_list:=@end{}

_optionalPARAM:,\W<parameter>=$0
_optionalPARAM:<S>=
_optionalPARAM:=@end{}

!parameter
!      ::=
!      type identifier { "[" "]" }
parameter:<_optionalModifier>\W<type> <ID><_optionalBR>=$0@end{}
parameter:=@fail{}

!type_specifier
!      ::=
!      "boolean"       | "byte"       | "char"       | "short"       | "int"       | "float"       | "long"       | "double"       | class_name       | interface_name
type_specifier:boolean=$0@end{}
type_specifier:byte=$0@end{}
type_specifier:char=$0@end{}
type_specifier:short=$0@end{}
type_specifier:int=$0@end{}
type_specifier:float=$0@end{}
type_specifier:long=$0@end{}
type_specifier:double=$0@end{}
type_specifier:double=$0@end{}
type_specifier:<class_name>=$0@end{}
type_specifier:=@fail{}

!class_name
!      ::=
!      identifier       | ( package_name "." identifier )
class_name:<ID>=$1@end{}
class_name:<package_name>\.<ID>=$0@end{}
class_name:=@fail{}

!package_name
!      ::=
!      identifier       | ( package_name "." identifier )
package_name:<ID>\.<package_name>=$0@end{}
package_name:<ID>=$1@end{}
package_name:=@fail{}

keyword:new=@end{}
keyword:=@fail{}

ID:<modifier>=@fail{}
ID:<keyword>=@fail{}
ID:<I>=$0@end{}
ID:=@fail{}

임창진의 이미지

아래 예제는 계산기 예제입니다
계산기 문법은아래처럼 inorder 로 tree 를 순회했을때 나오는 순서로 노드값을 적어주시면 됩니다.

        +
     /    \
   -       *
/    \    /  \
50   1    2   5


+ - 50 1 * 2 5

@lua 내장함수를 사용하시려면 gema 말고 gel 을 사용하셔야 합니다. gel 은 http://gema.sourceforge.net/new/gel.shtml 에 가셔서 받으시거나 참부한 파일을 사용하시면 됩니다.

@lua 내장함수는 그 내부의 lua code 에서 return 으로 돌려준 값을 print 합니다. (주의!!!)

@<STMT>=[$1]\n

user define recognizer 의 또다른 기능은 '=' 의 오른쪽 즉 $1 으로 값을 넘기기전에 그값을 변경할수 있다는 점 입니다.
위 코드에서 $1 에는 수식대신 계산한 값이 들어가 있습니다.

![

function calc( op , arg1 ,arg2)
	print("##" , op ,  arg1 ,arg2)

	if op == '+' then
		return arg1 + arg2	
	elseif op == '-' then
		return arg1 - arg2	
	elseif op == '*' then
		return arg1 * arg2	
	elseif op == '/' then
		return arg1 / arg2		
	end

	return 'NaN'
end

!]

\A=@set{matchorder;1}
<STMT>=[$1]\n

!STMT:<OP> <STMT> <STMT>=mo@var{matchorder}($0)@end{}@incr{matchorder}
!STMT:<OP> <STMT> <STMT>=$0@end{}
STMT:<OP> <STMT> <STMT>=@lua{return calc('$1',$2,$3)}@end{}
STMT:<D>=$0@end{}
STMT:=@fail{}

OP:\+=$0@end{}
OP:\/=$0@end{}
OP:\*=$0@end{}
OP:\-=$0@end{}
OP:=@fail{}

댓글 첨부 파일: 
첨부파일 크기
Package icon 0바이트
임창진의 이미지

String literal만 골라내는 패턴을 만들어가는 과정으로
상속에 대한설명을 하겠습니다.

'source----------------------------------------'
ABCDEF 가나다라 "ABC가나다라"
ABCDEF 가나다라 "ABC\"가나다라\""
ABCDEF 가나다라 "ABC\\"  가나다라  "ABCD\\"
'gema----------------------------------------'
"<u>"="[$1]"
'output----------------------------------------'
ABCDEF 가나다라 "[ABC가나다라]"
ABCDEF 가나다라 "[ABC\]"가나다라\"[]"
ABCDEF 가나다라 "[ABC\\]"  가나다라  "[ABCD\\]"

<u> recognizer 는 "" 로 둘러싸인 string 내부에 \" 와 같은 escape 문자를 인식하지 못하고 따라서 원하는 결과를 얻을수 없습니다.

<u> 는 바로뒤에 literal 이 따라오면 그 literal 을 제외한 모든 문자와는 match 하고 그 literal을 만나면 match 가 끝나게 됩니다

<u>뒤에 " 가 따라나오는 위의 예제를 custome recognizer (domain) 으로 구현하면 아래와 같습니다.

'source----------------------------------------'
ABCDEF 가나다라 "ABC가나다라"
ABCDEF 가나다라 "ABC\"가나다라\""
ABCDEF 가나다라 "ABC\\\"가나다라\\\""
'gema----------------------------------------'
"<QS>"="[$1]"
QS:"=@fail{}
QS:<U1>=$0
'output----------------------------------------'
ABCDEF 가나다라 "[ABC가나다라]"
ABCDEF 가나다라 "[ABC\]"가나다라\"[]"
ABCDEF 가나다라 "[ABC\\]"  가나다라  "[ABCD\\]"

QS (quoted string) 은 일단 <u>" 와 똑같은 일을 합니다.
여기에 \" 를 제대로 처리하도록 QSI (quoted string improved) 를 QS 를 상속받아서 만들면 다음과 같습니다.

'source----------------------------------------'
ABCDEF 가나다라 "ABC가나다라"
ABCDEF 가나다라 "ABC\"가나다라\""
ABCDEF 가나다라 "ABC\\\"가나다라\\\""
'gema----------------------------------------'
"<QSI>"="[$1]"
QS:"=@fail{}
QS:<U1>=$0
QSI::QS
QSI:\\"=$0
'output----------------------------------------'
ABCDEF 가나다라 "[ABC가나다라]"
ABCDEF 가나다라 "[ABC\"가나다라\"]"
ABCDEF 가나다라 "[ABC\\"  가나다라  ]"ABCD\\"

두번째 string literal 까지는 잘 되는데 마지막 string 이 문제군요
\ 뒤에 어떤문자가 따라나오면 그것을 그냥 string 으로 인식하도록 개선해서 SQI2 를 만들면 아래와 같이 됩니다.

'source----------------------------------------'
ABCDEF 가나다라 "ABC가나다라"
ABCDEF 가나다라 "ABC\"가나다라\""
ABCDEF 가나다라 "ABC\\\"가나다라\\\""
'gema----------------------------------------'
"<QSI2>"="[$1]"
QS:"=@fail{}
QS:<U1>=$0
QSI::QS
QSI:\\"=$0
QSI2::QSI
QSI2:\\<U1>=$0
'output----------------------------------------'
ABCDEF 가나다라 "[ABC가나다라]"
ABCDEF 가나다라 "[ABC\"가나다라\"]"
ABCDEF 가나다라 "[ABC\\]"  가나다라  "[ABCD\\]"

이제 만들어진 QSI2 를 사용해 보겠습니다.
흔히 소스코드에서 string literal 은 변경하지말고 A 란 변수를 aaa 로 rename 하고 싶은경우 혹은 그반대의 경우가 생기곤 합니다.
아래 예제는 ABC 를 abc 로 변경하는데 string literal 안에있는 ABC 는 그냥 놔두는 예제입니다.

'source----------------------------------------'
ABCDEF 가나다라 "ABC가나다라"
ABCDEF 가나다라 "ABC\"가나다라\""
ABCDEF 가나다라 "ABC\\\"가나다라\\\""
'gema----------------------------------------'
QS:"=@fail{}
QS:<U1>=$0
QSI::QS
QSI:\\"=$0
QSI2::QSI
QSI2:\\<U1>=$0
"<QSI2>"=$0
ABC=abc
가나다=ㄱㄴㄷ
'output----------------------------------------'
abcDEF ㄱㄴㄷ라 "ABC가나다라"
abcDEF ㄱㄴㄷ라 "ABC\"가나다라\""
abcDEF ㄱㄴㄷ라 "ABC\\"  ㄱㄴㄷ라  "ABCD\\"
임창진의 이미지

Gema 사용자 메뉴얼을 일부 번역했습니다. 시작한지 반년도 더 되었는데 처음 몇일 작업한거 이상으로 진도가 안나가는군요
Tex 원본도 같이 올려놓겠습니다. 필요하신분은 가져다 맘껏 수정해서 쓰시기 바랍니다.

임창진의 이미지

Gema 사용자 메뉴얼을 일부 번역했습니다. 시작한지 반년도 더 되었는데 처음 몇일 작업한거 이상으로 진도가 안나가는군요
Tex 원본도 같이 올려놓겠습니다. 필요하신분은 가져다 맘껏 수정해서 쓰시기 바랍니다.

임창진의 이미지

..

임창진의 이미지

databse column 이름을 java 에서 사용할 변수이름으로 변경하는 gema rule 입니다.

'source----------------------------------------'
FORM_ID
LINE_ID
FORM_NAME
FORM_TYPE
FORM_DESCRIPTION
FORM_VIEW
FORM_INPUT
FORM_HISTORY_TYPE
IS_LINE_CHANGEABLE
DEFAULT_CONTENTS
DEFAULT_CONTENTS_LOB
FORM_BEGIN_DATE
FORM_END_DATE
REGIST_USER_ID
REGIST_USER_NAME
REGIST_DATE
MODIFY_USER_ID
MODIFY_USER_NAME
MODIFY_DATE
'gema----------------------------------------'
<I>=@camelcase{$1}

camelcase:\A<A>=@downcase{$1}
camelcase:<A1><A>=@upcase{$1}@downcase{$2}
camelcase:_=
'output----------------------------------------'
formId
lineId
formName
formType
formDescription
formView
formInput
formHistoryType
isLineChangeable
defaultContents
defaultContentsLob
formBeginDate
formEndDate
registUserId
registUserName
registDate
modifyUserId
modifyUserName
modifyDate
임창진의 이미지

'source----------------------------------------'
| FORM_TYPE          |        |  |  NOT NULL  |  VARCHAR2  | 255  |    | 양식 구분(게시물,일반양식,워크스페이스…) 테이블 이름으로 하기로 함 (테이블명:PK COLUMN NAME)
| FORM_DESCRIPTION   |        |  |            |  VARCHAR2  | 255  |    | 양식 설명
| FORM_VIEW          |        |  |  NOT NULL  |  VARCHAR2  | 255  |    | 양식을 어떻게 표시할것인가 구분
| FORM_INPUT         |        |  |  NOT NULL  |  VARCHAR2  | 255  |    | 양식을 어떻게 입력받을것인가 구분
| FORM_HISTORY_TYPE  |        |  |  NOT NULL  | NUMBER     | 1    |    | 기안을 변경했을때 변경내용까지 이력에 남기는지 여부 (1:남김, 0:안남김)
| IS_LINE_CHANGEABLE |        |  |            | NUMBER     | 1    |    | 결재가 진핸중일때 결재선을 변경할수 있는지 여부(1:변경가능, 0:불가능)
| DEFAULT_CONTENTS   |        |  |  NOT NULL  |  VARCHAR2  | 2000 |    | 기본내용
 
'gema----------------------------------------'
@set{c;|}@set{N;0}
 
AWK:\L<U>=@awkinit{}@set{N;0}@AWK_LINE{$1}@end
 
AWK_LINE:<AWK_COLUMN>=@incr{N}@set{awk$N;$1}
AWK_LINE:\Z=@end
 
awkinit:\A=@set{tmp_cnt;1}\
@repeat{${N};@set{awk${tmp_cnt};}@incr{tmp_cnt}}@end
 
AWK_COLUMN:\A=@set{acl;0}
AWK_COLUMN:$c=@cmpn{${acl};0;@fail;@fail;@end}
AWK_COLUMN:<U1>=$1@incr{acl}
AWK_COLUMN:\Z=@cmpn{${acl};0;@fail;@fail;@end}
 
!--------------------------------
<AWK>= ${awk2} ${awk6}(${awk7})\n
'output----------------------------------------'
  FORM_TYPE            VARCHAR2  ( 255  )
 FORM_DESCRIPTION     VARCHAR2  ( 255  )
 FORM_VIEW            VARCHAR2  ( 255  )
 FORM_INPUT           VARCHAR2  ( 255  )
 FORM_HISTORY_TYPE   NUMBER     ( 1    )
 IS_LINE_CHANGEABLE  NUMBER     ( 1    )
 DEFAULT_CONTENTS     VARCHAR2  ( 2000 )
 DEFAULT_CONTENTS     VARCHAR2  ( 2000 )
dbjang의 이미지

허우행의 이미지

좋은 기능인데 아쉬운점이 성능이네요..
8000개 소스 파일을 하려고 했더니 느리고,
일괄 실행시 어느정도 진행되면 오류가 발생하네요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.