서브버전으로 관리되던 소스들을 git으로 이전하기로 마음 먹었다.

기존에 운용되던 서브버전 서버를 제거하고 git서버를 구축하려다가 그냥 남들 사는대로 살자 싶어서 비트버킷으로 결정했다.


 내친김에 비트버킷을 이용하여 자동화된 코드배포를 구현하고 싶었다.

crontab을 사용해 주기적으로 git clone을 하려다 너무 세련되 보이지 않아 찾다보니 webhooks 라는게 보였다.


이때쯤 김주원님의 "Envoy를 이용한 코드 배포 자동화" 글을 보았다.

envoy를 쓰는 방식도 끌리긴 했지만 나는 그다지 큰 시스템도 아니라... 

그냥 간단하게 써도 될듯했고... webhook을 써보고 싶었다... ^^;;;


 그래서 간단하게 반응할 php를 만들었다...

다른 서버에 복사하기도 귀찮고 정리좀 할까 싶다가 composer package 를 만들어야겠다 싶어서 만들었다.

할꺼 많은데 자꾸 일을 벌인다...


계획 

  • master 브랜치만 적용
    - Git Flow 을 쓸때 master만 배포하고 이 외 develop 이나 feature 등은 배포시에 제외한다. 

  • bitbucket의 webhook 접근만 허용하자.
    - 공개된 주소이므로 아무나 접근이 가능했다. 그래서 bitbucket의 IP인 104.192.143.1~255 까지만 허용하기로 했다.

  • 로그를 남기자
    - 나중을 위해 뭐라도 남겨야....

  • 알림같은게 되었으면 좋겠는데...
    Pushbullet을 사용했다. slack쓸껄 후회도 했다... ㅡ,.ㅡa

  • 가능하면 수정된 파일만 바꾼다.
    - git으로 관리되지 않은 설정파일 혹은 업로드된파일 등은 건드리지 않는다.

이런 계획을 세웠다.



이제부턴 존칭으로.. ^^;;



준비


테스트 및 포스팅 편의를 위해 node1, node2, node3, node4 를 셋팅하여 가상의 상황을 만들었습니다.

주소는 아래와 같습니다. 

 http://node1.wbp.co.kr

 http://node2.wbp.co.kr

 http://node3.wbp.co.kr 

 http://node4.wbp.co.kr

※ 테스트로 셋팅한 환경은 일정시간 유지하겠지만 언제 없어질지 모릅니다. 


비트버킷에 배포가될 코드의 repository를 생성하겠습니다.

git@bitbucket.org:DexterPark/test-site.git 이고...

https://bitbucket.org/DexterPark/test-site 로 접근 가능합니다.

예제로 쓸꺼라 공개 repository이지만 실제는 비공개로 하셔야 겠지요?? ^^ 


요약




요약 하자면 이러한 구조입니다.


1. 개발장비에서 비트버킷에 push를 한다. 

2. master로 push가 들어오면 지정한 url로 hook을 날린다. (브렌치는 master외 다른 것으로 설정 가능)


3. hook을 받은 서버는 비트버킷으로 pull을 요청한다...

사실 pull은 아니고 fetch이다...


4. 그리고 결과를 Pushbullet 을 통해 알려준다.



설치


node1 에 설치해보겠습니다.



$ mkdir /home/git

$ cd /home/git

$ git clone --mirror git@bitbucket.org:DexterPark/test-site.git


/home/git를 만들고 

repository를 clone mirror하였습니다.




/home/git/test-site.git 로 생성되었네요... 

해당 경로가 필요하니 기억해 둡니다.


그리고 node1 으로 이동합니다.



구조는 간단합니다. 


웹 루트는 /home/node1/public_html 이지만 /home/node1 전체를 관리하겠습니다.

왜냐면 저는 프레임웍을 사용하니까요... ^^;

여기도 경로도 아래 설정할때 사용되니 기억해 주세요...


아까 composer로 만들었다던 bitdepoly를 설치하겠습니다.

( 참고 : https://packagist.org/packages/dexterys/bitdepoly )



$ composer require dexterys/bitdepoly


여느 composer 설치법과 같습니다.


이제 bitbucket에서 hook을 받을 파일을 생성합니다.


파일은 /home/node1/public_html/bitbucket-hook.php 에 아래와 같이 생성하겠습니다.

https://bitbucket.org/DexterPark/bitdepoly/src 로 가시면 샘플코드를 비롯한 모든 소스코드를 보실 수 있습니다.


<?php require_once __DIR__ . '/../vendor/autoload.php'; use BitDepoly\Hook; $depoly = new Hook(); $depoly->server_name = 'node1'; // 서버의 이름 $depoly->branch = 'master'; // master 브렌치만 적용합니다. $depoly->repo_dir = '/home/git/test-site.git'; // 아까 git clone한 경로를 적어줍니다. $depoly->web_root_dir = '/home/node1'; // 여기도 아까 기억해 달라던 적용될 경로입니다. $depoly->log_file = '/home/node1/deploy.log'; // 이건 로그를 기록할 위치예요. 적당한 위치로 설정하세요.

$depoly->pushbullet_token = ''; // pushbullet의 token 을 적어주세요. (아래설명) $depoly->pushbullet_user = array('xxxx@wbp.co.kr');// 알림 받을 사람 (아래설명)

 

$depoly->deployment();


저는 pushbullet 을 이용하여 알림 받도록 하였습니다.

slack 으로 하려다 다른곳에서도 사용하고 있어서 pushbullet으로 적용하였습니다.

알림을 받지 않으시려면 token 값을 비워두시면 됩니다.


아래 동영상에서 보이는 알림기능을 합니다.

https://pushbullet.com/ 이곳을 통해 가입하셔서 무료로 사용하실 수 있습니다.


또한 $depoly->pushbullet_user에는 배열로 array('xxxx@wbp.co.kr', 'xxxx222@wbp.co.kr'); 와같이 넘겨주시면 여러명에게 전송 가능합니다.

같은 방법으로 node2~4의 서버에도 동일한 방법으로 설치하였습니다.


/home/node1/public_html/bitbucket-hook.php 에 생성후 자신에 맞게 설정을 바꾸셨으면 이제 bitbucket 에서도 설정해주어야 합니다.



bitbucket repository로 이동후 webhook을 설정합니다.



add webhook 을 선택하시면 아래와 같이 나옵니다.




아까 생성한 bitbucket-hook.php 의 경로를 적어주세요.

비트버킷의 IP인 104.192.143.x 에만 반응합니다. 브라우져로 접속시 에러만 출력해요. 

http://node2.wbp.co.kr/bitbucket-hook.php  <- 에러메시지 구경해 보기


4대의 서버에서 테스트 할것이므로 node2~4까지 같은방법으로 등록했습니다.




이제 다 되었습니다!! 


이제 테스트를 해보겠습니다.

이미지로 설명하는것 보다 동영상이 나을것 같아서 동영상으로 만들어 보았습니다.

( 소리없음 )


이거 녹화한다고 떨리네요... ^^;;;


1. 일단 node1~4까지 열었습니다. 모두 "Hi Dexter" 라고 나오고 있네요.

2. local에 설치한 git bash에서 테스트 합니다. 

3. origin과 같도록 pull부터 하고 master브렌치의 index.php 에서 Hi Dexter를 Hello Dexter 로 바꾸었습니다.

4. 그리고 origin master로 push합니다.

5. 눈에 보이진 않지만 push받은 비트버킷에서 각 서버로 webhook을 날리고 각 서버들은 수정된 사항을 origin master에서 받아 옵니다.

6. 각 서버들은 받아온 수정사항을 적용한 후 설정된 사람에게 알림을 보냅니다. 

7. 4대가 모두 잘 배포되었다는 알림을 확인한 후 실제로 바뀌었는지 브라우져에서 확인 합니다.

8. 이번엔 master가 아닌 다른 브렌치에서 작업된것이 적용되진 ㅇ낳는지 테스트 해봅니다.

9. hotfix 브렌치를 생성하고 index.php 파일의  Hello Dexter 아래에다가 "hotfix" 라고 추가해 봅니다.

10. hotfix 브렌치를 origin에 push하고 반응을 기다려 봅니다. 

11. 의도한대로 반응이 없습니다. 

12. 그럼 master에서 merge를 한후 push를 해보겠습니다.

13. 배포되는데 조금 걸렸습니다만 정상적으로 알림이 오고 브라우져로 확인해보니 수정되었습니다.


잘 되네요... 


글 재주가 없어 잘 전달 되었는지 모르겠습니다.

긴글 읽어주셔서 감사합니다.


이것으로 마무리 하겠습니다...





'개발 > 옛날꺼' 카테고리의 다른 글

Bitbucket을 이용한 코드배포  (0) 2017.03.23
Docker image 배포  (0) 2017.03.07
재미있는 Docker  (0) 2017.03.07
자바스크립트 정규식  (0) 2012.01.19
제이쿼리를 이용한 타이머 기능  (0) 2011.10.10
jQuery 동영상 강의...  (0) 2010.09.24


 아까 글에 이어 ( http://unlack.com/126 ) 바로 이어 쓰네요... ^^

저 고래는 도커의 상징인 케릭터인데요 컨테이너를 적제하는 저 모습이 도커를 잘 표현한 케릭인거 같아 맘에 듭니다. 


 디테일 하게 들어가려면 조금 걸리겠지만 간단한 개발서버 세팅정도는 기존에 vm웨어를 사용해본 경험이 있으시고 리눅스를 조금 다루어본 분이라면 빠르면 하루만에 바로 사용할 수 있을정도로 쉽습니다.


 제가 만든 이미지 Dockerfile을 비트버킷(git)에 공개해 놓았습니다.


https://bitbucket.org/wbp/web-server

git clone https://DexterPark@bitbucket.org/wbp/web-server.git


간단하게 nginx, php7, composer, git 이 설치됩니다.

그리고 리눅스 한글언어팩(?명칭을 모르겠네요..)도 설치가 되고요.

sql은 따로 사용하여 설치에 포함 시키지 않았습니다.

php 패키지는 

RUN apt-get -y --force-yes install php7.0-fpm \
                   php7.0-common \
                   php7.0-cli \
                   php7.0-mysqlnd \
                   php7.0-mcrypt \
                   php7.0-curl \
                   php7.0-bcmath \
                   php7.0-mbstring \
                   php7.0-soap \
                   php7.0-xml \
#                  php7.0-zip \
                   php7.0-json \
                   php7.0-imap \
                   php7.0-gd 
#                  php-xdebug 

요렇게 설치가 되는데 안쓰시는건 # 으로 주석처리 하시면 됩니다.


nodejs와 npm은 주석처리 되어있어요.

같이 설치되는 이미지를 생성하시려면 빌드전에 주석해재 해주시면 


빌드는 요렇게...

docker build -t dexter-docker:latest .


실행은 요런식으로....

docker run -d --name web-server -p 80:80 -p 443:443 -P  dexter-docker:latest


빌드가 귀찮으신분은 dockerhub에도 올려 놓았으니 확인해 보시고요. https://hub.docker.com/r/dexterys/web-server/

요렇게 바로 받으셔도 됩니다.

docker pull dexterys/web-server:latest


운영에 필요한 파일들은 모두 /data 에 이동되어 관리됩니다.

    /data/www
    /data/etc
    /data/logs


Symlink 걸어 놓았습니다.

/var/www -> /data/www /etc/nginx -> /data/etc /var/log/nginx -> /data/logs


수정해야할 사항이나 질문 있으시면 비트버킷 issues에 작성해주세요.

https://bitbucket.org/wbp/web-server/issues?status=new&status=open


'개발 > 옛날꺼' 카테고리의 다른 글

Bitbucket을 이용한 코드배포  (0) 2017.03.23
Docker image 배포  (0) 2017.03.07
재미있는 Docker  (0) 2017.03.07
자바스크립트 정규식  (0) 2012.01.19
제이쿼리를 이용한 타이머 기능  (0) 2011.10.10
jQuery 동영상 강의...  (0) 2010.09.24



 그동안 귀에 딱지가 생기도록 들었던 도커(DOCKER)를 이제야 접했습니다.
바쁘다는 핑계로 뭐든 한박자 늦게 접하고 있네요... ( 바쁜게 아니라 귀찮아서겠지... )


몇일 가지고 놀아본 결과 이놈 물건입니다.

바빠서(귀찮아서) 외면해왔던게 오히려 덜 바쁘게 해줄 보물 같은 존재였다니....


 간단히 말하면 리눅스 컨테이너라걸 쉽게 사용할수 있는 뭐 그런건데.
이미 접해왔던 VM웨어같은 가상화랑 비슷한데 또 이거랑은 다릅니다... 


몇일 공부한 어설픈 내가 설명하기보다 좋은 사이트가 있어서 링크를 추가합니다.


http://pyrasis.com/private/2014/11/30/publish-docker-for-the-really-impatient-book

"가장 빨리만나는 도커"의 저자이신 이재홍님의 사이트인데 원고를 공개 하셨습니다.

감사합니다.


이걸 참고하며 많은 도움이 되었습니다.

또한 참고할 만한 사이트 몇개 링크를 걸고 이 글은 마치겠습니다.



Docker Swarm을 이용한 쉽고 빠른 분산 서버 관리

https://subicura.com/2017/02/25/container-orchestration-with-docker-swarm.html


도커(Docker) 튜토리얼 : 깐 김에 배포까지

http://blog.nacyot.com/articles/2014-01-27-easy-deploy-with-docker/



Youtube 박재성님의 Docker 강의부분

https://www.youtube.com/watch?v=U_F-eNo3uM0&feature=youtu.be&list=PLqaSEyuwXkSrJ5Z4y8oCffAOPvGBiNAST



Youtube 의 Docker 공식 채널

https://www.youtube.com/channel/UC76AVf2JkrwjxNKMuPpscHQ





'개발 > 옛날꺼' 카테고리의 다른 글

Bitbucket을 이용한 코드배포  (0) 2017.03.23
Docker image 배포  (0) 2017.03.07
재미있는 Docker  (0) 2017.03.07
자바스크립트 정규식  (0) 2012.01.19
제이쿼리를 이용한 타이머 기능  (0) 2011.10.10
jQuery 동영상 강의...  (0) 2010.09.24



정규식
이전에 정규식을 다뤄 본 경험이 없으면 용어와 개념이 익숙하지 않겠지만 생각처럼 생소하지는 않을 것입니다.

하드 디스크에서 파일을 검색하는 방법에 대해 생각해 보십시오.
대부분의 경우 ? 및 * 문자를 사용하여 파일을 찾습니다.
? 문자는 파일 이름에서 문자 하나를 찾는 반면 *는 0개 이상의 문자를 찾습니다.
예를 들어, 'data?.dat'와 같은 패턴은 다음과 같은 파일을 찾습니다.

data1.dat
data2.dat
datax.dat
dataN.dat

? 문자 대신 * 문자를 사용하면 좀 더 많은 파일을 찾게 됩니다. 'data*.dat'는 다음과 같은 파일을 찾습니다.

data.dat
data1.dat
data2.dat
data12.dat
datax.dat
dataXYZ.dat

이러한 파일 검색 방법은 매우 유용하지만 제한되어 있습니다.
? 및 * 와일드카드 문자의 제한된 기능으로 정규식의 기능을 짐작할 수 있지만 정규식은 훨씬 더 강력하고 융통성이 있습니다.


정규식의 기원
정규식의 기원을 추적해 보면 인간 신경계의 작용 방법에 대한 초기 연구로까지 올라갑니다.
신경 생리학자인 Warren McCulloch와 Walter Pitts는 이러한 신경계를 설명할 수 있는 수학적 방법을 개발했습니다.

1956년 미국 수학자인 Stephen Kleene은 McCulloch와 Pitts의 초기 연구를 기반으로 정규식의 개념을 소개한
Representation of Events in Nerve Nets라는 논문을 발표했습니다.
그가 "정규 집합의 대수학"이라고 표현한 것을 설명하는 용어가 "정규식"입니다.

그 이후로 그의 연구는 Unix의 핵심 개발자인 Ken Thompson이 만든 초기 계산 검색 알고리즘에 적용되었습니다.
그러나 정규식이 실제로 적용된 최초의 응용 프로그램은 qed라는 Unix 편집기였습니다.

그리고 그 나머지는 말 그대로 옛날 이야기입니다.
정규식은 그 후 텍스트 기반 편집기 및 검색 도구에서 중요한 부분을 차지하게 되었습니다.


정규식 사용
일반적인 찾기 및 바꾸기 작업에서 찾을 문자열을 정확하게 입력해야 합니다.
이 기술은 정적 텍스트에서 이루어지는 간단한 찾기 및 바꾸기 작업에는 적합하지만,
융통성이 부족하며 동적 텍스트에서는 찾기 작업을 수행하기가 어렵다는 단점이 있습니다.

정규식을 통해 다음을 수행할 수 있습니다.

문자열에 있는 패턴을 테스트합니다.
예를 들어, 입력 문자열을 테스트하여 전화 번호 패턴 또는 신용 카드 번호 패턴이 문자열에 있는지 볼 수 있습니다.
이를 데이터 유효성이라고 합니다.

텍스트를 바꿉니다.
정규식을 사용하여 문서에서 특정 텍스트를 식별하고 이를 완전히 제거하거나 다른 텍스트로 바꿀 수 있습니다.

패턴 일치를 기반으로 문자열에서 부분 검색 문자열을 추출합니다.

문서 또는 입력 필드에서 특정 텍스트를 찾을 수 있습니다.
예를 들어, 전체 웹 사이트를 검색하여 오래된 자료를 제거하고 일부 HTML 서식 태그를 바꿔야 할 경우
정규식을 사용하면 찾는 자료 또는 HTML 서식 태그가 특정 파일에 있는지 여부를 테스트할 수 있습니다.
이 방법을 사용하면 영향을 받는 파일의 범위를 제거되었거나 변경된 내용이 있는 파일로 좁힐 수 있습니다.
그런 다음 정규식을 사용하여 오래된 자료를 제거하고 대체할 태그를 찾아서 바꿀 수 있습니다.

문자열 처리 기능이 지원되지 않는 언어에서도 정규식을 유용하게 사용할 수 있습니다.
Visual Basic에 포함된 VBScript에는 다양한 문자열 처리 기능이 있는 반면 JScript에는 C와 마찬가지로 이러한 기능이 없습니다.
정규식은 JScript의 문자열 처리 기능을 상당히 향상시켰을 뿐만 아니라,
단일 식에서 여러 문자열을 처리할 수 있으므로 VBScript에서도 효율적으로 사용할 수 있습니다.


정규식 구문
정규식은 일반 문자(예: a에서 z)와 메타문자로 알려진 특수 문자로 구성된 텍스트 패턴입니다.
패턴은 텍스트 본문을 검색할 때 일치하는 문자열을 하나 이상 설명합니다.
정규식은 검색되는 문자열과 일치하는 문자 패턴을 찾는 템플릿의 역할을 합니다.

일반적으로 볼 수 있는 몇 가지 정규식 예는 다음과 같습니다.

JScript 정규식의 경우

/^[ \t]*$/ 빈 줄을 찾습니다.
/\d{2}-\d{5}/ 2자리, 하이픈 및 5자리로 구성된 ID 번호를 찾습니다.
/<(.*)>.*<\1>/ HTML 태그를 찾습니다.


\ 이스케이프 문자

\
문자는 그 다음 문자를 특수 문자, 리터럴, 역참조, 또는 8진수 이스케이프로 표시합니다.
'n'은 문자 "n"을 찾고 '\n'은 줄 바꿈 문자를 찾습니다. '\\' 시퀀스는 "\"를 찾고 '\('는 "("를 찾습니다.

그외에...

\b 단어의 경계, 즉 단어와 공백 사이의 위치를 찾습니다. 예를 들어, "er\b"는 "never"의 "er"는 찾지만 "verb"의 "er"는 찾지 않습니다.
\B 단어의 비경계를 찾습니다. "er\B"는 "verb"의 "er"는 찾지만 "never"의 "er"는 찾지 않습니다.

\d 숫자 문자를 찾습니다. [0-9]와 같습니다.
\D 비숫자 문자를 찾습니다. [^0-9]와 같습니다.

\s 공백, 탭, 폼피드 등의 공백을 찾습니다. "[ \f\n\r\t\v]"와 같습니다.
\S 공백이 아닌 문자를 찾습니다. "[^ \f\n\r\t\v]"와 같습니다.

\w 밑줄을 포함한 모든 단어 문자를 찾습니다. "[A-Za-z0-9_]"와 같습니다.
\W 모든 비단어 문자를 찾습니다. "[^A-Za-z0-9_]"와 같습니다.

\cx X 가 나타내는 제어 문자를 찾습니다. 예를 들어, \cM은 Control-M 즉, 캐리지 리턴 문자를 찾습니다.
x 값은 A-Z 또는 a-z의 범위 안에 있어야 합니다. 그렇지 않으면 c는 리터럴 "c" 문자로 간주됩니다.

\f 폼피드 문자를 찾습니다. \x0c와 \cL과 같습니다.
\n 줄 바꿈 문자를 찾습니다. \x0a와 \cJ와 같습니다.
\r 캐리지 리턴 문자를 찾습니다. \x0d와 \cM과 같습니다.
\t 탭 문자를 찾습니다. \x09와 \cI와 같습니다.
\v 수직 탭 문자를 찾습니다. \x0b와 \cK와 같습니다.

\xn 여기서 n은 16진수 이스케이프 값입니다. 16진수 이스케이프 값은 정확히 두 자리여야 합니다.
예를 들어, '\x41'은 "A"를 찾고 '\x041'은 '\x04'와 "1"과 같습니다. 정규식에서 ASCII 코드를 사용할 수 있습니다.
\num 여기서 num은 양의 정수입니다. 캡처한 문자열에 대한 역참조입니다.
예를 들어, '(.)\1'은 연속적으로 나오는 동일한 문자 두 개를 찾습니다.
\n 8진수 이스케이프 값이나 역참조를 나타냅니다.
\n 앞에 최소한 n개의 캡처된 부분식이 나왔다면 n은 역참조입니다.
그렇지 않은 경우 n이 0에서 7 사이의 8진수이면 n은 8진수 이스케이프 값입니다.
\nm 8진수 이스케이프 값이나 역참조를 나타냅니다.
\nm 앞에 최소한 nm개의 캡처된 부분식이 나왔다면 nm은 역참조입니다.
\nm 앞에 최소한 n개의 캡처가 나왔다면 n은 역참조이고 뒤에는 리터럴 m이 옵니다.
이 두 경우가 아닐 때 n과 m이 0에서 7 사이의 8진수이면 \nm은 8진수 이스케이프 값 nm을 찾습니다.
\nml n이 0에서 3 사이의 8진수이고 m과 l이 0에서 7 사이의 8진수면 8진수 이스케이프 값 nml을 찾습니다.
\un n은 4 자리의 16진수로 표현된 유니코드 문자입니다. 예를 들어, \u00A9는 저작권 기호(ⓒ)를 찾습니다


\문자 이외의 모든 메타문자

^
입력 문자열의 시작 위치를 찾습니다. Multiline 속성이 설정되어 있으면 ^는 '\n' 또는 '\r' 이후의 위치를 찾습니다.
대괄호 식 안에서 사용될 때는 대괄호에 포함된 문자 집합을 제외한 문자열을 찾습니다.
$ 입력 문자열의 끝 위치를 찾습니다. Multiline 속성이 설정되어 있으면 '\n' 또는 '\r' 이전의 위치를 찾습니다.
* 부분식의 선행 문자를 0개 이상 찾습니다. 예를 들어, 'zo*'는 "z", "zoo" 등입니다. *는 {0,}와 같습니다.
+ 부분식의 선행 문자를 한 개 이상 찾습니다. 예를 들어, 'zo+'는 "zo", "zoo" 등이지만 "z"는 아닙니다. +는 {1,}와 같습니다.
? 부분식의 선행 문자를 0개 또는 한 개 찾습니다. 예를 들어, "do(es)?"는 "do" 또는 "does"의 "do"를 찾습니다. ?는 {0,1}과 같습니다.
{n} 정확히 n개 찾습니다. 예를 들어, 'o{2}'는 "Bob"의 "o"는 찾지 않지만 "food"의 o 두 개는 찾습니다.
{n,} n개 이상을 찾습니다. 예를 들어, 'o{2}'는 "Bob"의 "o"는 찾지 않지만 "foooood"의 모든 o는 찾습니다.
'o{1,}'는 "o+"와 같고, 'o{0,}'는 "o*"와 같습니다.
{n,m}최소 n개, 최대 m개 찾습니다. 예를 들어, "o{1,3}"은 "fooooood"의 처음 세 개의 o를 찾습니다.
"o{0,1}"은 "o?"와 같습니다. 쉼표와 숫자 사이에는 공백을 넣을 수 없습니다.
? 이 문자가 다른 한정 부호(*, +, ?, {n}, {n,}, {n,m})의 바로 뒤에 나올 경우 일치 패턴은 제한적입니다.
기본값인 무제한 패턴은 가능한 많은 문자열을 찾는 데 반해 제한적인 패턴은 가능한 적은 문자열을 찾습니다.
예를 들어, "oooo" 문자열에서 "o+?"는 "o" 한 개만 찾고, "o+"는 모든 "o"를 찾습니다.
. "\n"을 제외한 모든 단일 문자를 찾습니다. "\n"을 포함한 모든 문자를 찾으려면 '[.\n]' 패턴을 사용하십시오


패턴식과 문자집합

(pattern)
pattern을 찾아 검색한 문자열을 캡처합니다.
캡처한 문자열은 Jscript의 경우 $0...$9 속성을 이용하여 결과로 나오는 Matches 컬렉션에서 추출할 수 있습니다.
괄호 문자인 ( )를 찾으려면 "\(" 또는 "\)"를 사용하십시오.

(?:pattern) pattern을 찾지만 검색한 문자열을 캡처하지 않습니다.
즉, 검색한 문자열을 나중에 사용할 수 있도록 저장하지 않는 비캡처 검색입니다.
이것은 패턴의 일부를 "or" 문자(|)로 묶을 때 유용합니다.
예를 들어, "industr(?:y|ies)"는 "industry|industries"보다 더 경제적인 식입니다.

(?=pattern) 포함 예상 검색은 pattern과 일치하는 문자열이 시작하는 위치에서 검색할 문자열을 찾습니다.
이것은 검색한 문자열을 나중에 사용할 수 있도록 캡처하지 않는 비캡처 검색입니다.
예를 들어, "Windows(?=95|98|NT|2000)"는 "Windows 2000"의 "Windows"는 찾지만
"Windows 3.1"의 "Windows"는 찾지 않습니다.
예상 검색은 검색할 문자열을 찾은 후 예상 검색 문자열을 구성하는 문자 다음부터가 아니라
마지막으로 검색한 문자열 바로 다음부터 찾기 시작합니다.

(?!pattern) 제외 예상 검색은 pattern과 일치하지 않는 문자열이 시작하는 위치에서 검색할 문자열을 찾습니다.
이것은 검색한 문자열을 나중에 사용할 수 있도록 캡처하지 않는 비캡처 검색입니다.
예를 들어, "Windows(?!95|98|NT|2000)"는 "Windows 3.1"의 "Windows"는 찾지만
"Windows 2000"의 "Windows"는 찾지 않습니다. 예상 검색은 검색할 문자열을 찾은 후
예상 검색 문자열을 구성하는 문자 다음부터가 아니라 마지막으로 검색한 문자열 바로 다음부터 찾기 시작합니다.

x|y x 또는 y를 찾습니다.
예를 들어, "z|food"는 "z" 또는 "food"를 찾습니다. "(z|f)ood"는 "zood" 또는 "food"를 찾습니다.

[xyz] 문자 집합입니다. 괄호 안의 문자 중 하나를 찾습니다.
예를 들어, "[abc]"는 "plain"의 "a"를 찾습니다.

[^xyz] 제외 문자 집합입니다. 괄호 밖의 문자 중 하나를 찾습니다.
예를 들어, "[^abc]"는 "plain"의 "p"를 찾습니다.

[a-z] 문자 범위입니다. 지정한 범위 안의 문자를 찾습니다.
예를 들어, "[a-z]"는 "a"부터 "z" 사이의 모든 소문자를 찾습니다.

[^a-z] 제외 문자 범위입니다. 지정된 범위 밖의 문자를 찾습니다.
예를 들어, "[^a-z]"는 "a"부터 "z" 사이에 없는 모든 문자를 찾습니다.



정규식 만들기
정규식은 산술식을 만드는 것과 같은 방법으로 구성됩니다.
즉, 작은 식은 다양한 메타문자 및 연산자를 사용하여 결합되며 이는 더 큰 식을 만듭니다.

한 쌍의 구분 기호 안에 식 패턴의 다양한 구성 요소를 넣어서 정규식을 구성합니다.
JScript에서 구분 기호는 한 쌍의 슬래시(/) 문자입니다. 예를 들어 다음과 같습니다.

/expression/

VBScript에서는 한 쌍의 따옴표("")로 정규식을 구분합니다. 예를 들어 다음과 같습니다.

"expression"

위의 두 예제에서 정규식 패턴(expression)은 RegExp 개체의 Pattern 속성에 저장됩니다.

정규식의 구성 요소는 개별 문자, 문자 집합, 문자 범위, 문자 간 선택 또는 이러한 모든 구성 요소의 조합일 수 있습니다.



우선 순위
일단 정규식을 구성하면 산술식처럼 평가됩니다. 즉, 왼쪽에서 오른쪽으로 평가되고 우선 순위에 따라 이루어집니다.

아래 표는 다양한 정규식 연산자의 우선 순위를 가장 높은 것에서 가장 낮은 것까지 보여줍니다.

연산자 설명

\
이스케이프
() (?:) (?=) [] 괄호 및 대괄호
* + ? {n} {n,} {n,m} 한정 기호
^ $ \anymetacharacter 앵커 및 시퀀스
| 선택 연산자(OR)



일반 문자
일반 문자는 명시적으로 메타문자로 지정되지 않은 인쇄할 수 있는 문자 및 인쇄할 수 없는 문자로 구성됩니다.
여기에는 모든 대소문자, 모든 숫자, 모든 구두점 및 일부 기호가 포함됩니다.

가장 간단한 정규식 양식은 검색된 문자열에서 문자 자체를 찾는 단일 일반 문자입니다.
예를 들어, 단일 문자 패턴 'A'는 검색된 문자열에 나타날 때마다 'A' 문자를 찾습니다.

단일 문자 정규식 패턴의 몇 가지 예는 다음과 같습니다.

/a/
/7/
/M/

여러 개의 단일 문자를 결합하여 좀 더 큰 식을 만들 수 있습니다.
예를 들어, 다음 JScript 정규식은 단일 문자 식인 'a', '7' 및 'M'을 결합하여 만들어진 식입니다.

/a7M/

여기에는 연결 연산자가 필요하지 않으며 문자를 하나씩 나열하기만 하면 됩니다.


특수 문자
문자열을 찾을 때 특별히 처리해야 하는 여러 가지 메타문자가 있습니다.
이러한 특수한 역할을 하는 메타 문자를 찾으려면 먼저 이를 이스케이프해야 합니다.
즉, 특수 문자 앞에 백슬래시 문자(\)를 입력해야 합니다. 다음 표는 특수 문자와 그 의미를 보여줍니다.

특수 문자 설명

$ 입력 문자열의 끝 위치를 찾습니다. $ 문자 자체를 찾으려면 \$ 를 사용하십시오.
( 부분식의 시작을 나타냅니다. ( 를 찾으려면 \( 를 사용하십시오.
* 부분식의 선행 문자를 0개 이상 찾습니다. * 문자를 찾으려면 \*를 사용하십시오.
+ 부분식의 선행 문자를 한 개 이상 찾습니다. + 문자를 찾으려면 \+를 사용하십시오.
. 줄 바꿈 문자인 \n을 제외한 모든 단일 문자를 찾습니다 .를 찾으려면 \.를 사용하십시오.
[ 대괄호 식의 시작 위치를 찾습니다. [를 찾으려면 \[를 사용하십시오.
? 부분식의 선행 문자를 0 또는 1 개 찾거나, 제한적인 한정 기호를 나타냅니다. ?를 찾으려면 \?를 사용하삼.
\ 그 다음 문자를 특수 문자, 리터럴, 역참조 또는 8진수 이스케이프로 출력. \를 찾으려면 \\를 사용하삼.
^ 문자열의 시작 위치를 찾습니다. ^ 문자 자체를 찾으려면 \^를 사용하십시오.
또는 대괄호 식 안에서 사용될 때는 대괄호에 포함된 문자 집합을 제외한 문자열을 찾습니다.
{ 한정 기호 식의 시작 위치를 찾습니다. {를 찾으려면 \{를 사용하십시오.
| 두 항목 간의 선택을 나타냅니다. |를 찾으려면 \|를 사용하십시오.


인쇄할 수 없는 문자
가끔 사용하는 문자 중 인쇄할 수 없는 유용한 문자가 여러 개 있습니다.
아래 표에서는 인쇄할 수 없는 이들 문자를 나타낼 때 사용되는 이스케이프 시퀀스를 보여줍니다.

\cx x가 나타내는 제어 문자를 찾습니다. 예를 들어, \cM은 Control-M 즉, 캐리지 리턴 문자를 찾습니다.
x 값은 A-Z 또는 a-z의 범위 안에 있어야 합니다. 그렇지 않으면 c는 리터럴 "c" 문자로 간주됩니다.
\f 폼피드 문자를 찾습니다. \x0c와 \cL과 같습니다.
\n 줄 바꿈 문자를 찾습니다. \x0a와 \cJ와 같습니다.
\r 캐리지 리턴 문자를 찾습니다. \x0d와 \cM과 같습니다.
\s 공백, 탭, 폼피드 등의 공백을 찾습니다. "[ \f\n\r\t\v]"와 같습니다.
\S 공백이 아닌 문자를 찾습니다. "[^ \f\n\r\t\v]"와 같습니다.
\t 탭 문자를 찾습니다. 와 \cI와 같습니다.
\v 수직 탭 문자를 찾습니다. \x0b와 \cK와 같습니다.



문자 일치

마침표 . 는 문자열에서 줄 바꿈 문자(\n)를 제외한 단일 인쇄 또는 비인쇄 문자를 찾습니다

다음은 'aac', 'abc', 'acc', 'adc' 뿐만 아니라 'a1c', 'a2c', 'a-c', 'a#c'를 나타내기도 합니다.

/a.c/

입력 문자열의 일부에 마침표(.)가 있는 파일 이름이 포함된 문자열을 찾을 경우
정규식에서 마침표 앞에 백슬래시(\) 문자를 입력하십시오.
예를 들어 다음 JScript 정규식은 'filename.ext'를 찾습니다.

/filename\.ext/


대괄호 [] 안에 문자들을 넣으면 대괄호식이 됩니다.
즉, 하나 이상의 개별 문자를 대괄호([ ]) 안에 입력하여 찾을 문자 목록을 만들 수 있습니다.
다른 곳에서와 마찬가지로 대괄호 안에서 일반 문자는 문자 자체를 나타내므로
입력 텍스트에서 문자 자체를 찾지만 대괄호 식에서 대부분의 특수 문자는 문자 자체를 찾지 않습니다.

다음은 몇 가지 예외입니다.

']' 문자는 목록의 첫째 항목이 아닌 경우 이 목록을 종료합니다.
목록에서 ']' 문자 자체를 찾으려면 이를 '[' 바로 다음에 놓으십시오.

'\' 문자는 여전히 이스케이프 문자로 사용됩니다.
'\' 문자를 찾으려면 '\\'를 사용하십시오.

대괄호 식으로 묶인 문자는 대괄호 식이 나타나는 정규식의 위치에 해당하는 단일 문자만을 찾습니다.

다음 JScript 정규식은 'Chapter 1', 'Chapter 2', 'Chapter 3', 'Chapter 4' 및 'Chapter 5' 등을 검색합니다.

/Chapter [12345]/

단어 'Chapter' 및 이어지는 공백은 대괄호 내에 있는 문자와 관련된 위치에 고정됩니다.
그러면 대괄호 식은 단어 'Chapter' 및 공백 바로 다음에 오는 단일 문자 위치에 해당하는 문자 집합만 지정하므로
여기서는 아홉 번째 문자 위치입니다.

검색 문자의 범위를 표현하려면 하이픈 문자 - 를 사용하여 시작하는 문자와 끝나는 문자를 구분합니다.
개별 문자의 문자 값은 범위에서의 상대적 순서를 결정합니다.

다음 JScript 정규식에는 위의 대괄호로 묶인 목록과 같은 범위식이 들어 있습니다.

/Chapter [1-5]/


범위가 이러한 방식으로 지정되면 시작하는 값과 끝나는 값이 범위에 포함됩니다.
'시작하는 값'은 유니코드 정렬 순서에서 '끝나는 값' 보다 앞쪽의 값이어야 합니다.

대괄호 식에 하이픈 문자를 포함시켜려면 다음 중 하나를 수행해야 합니다.

백슬래시로 이스케이프합니다.
[\-]

대괄호로 묶은 목록의 시작 또는 끝에 하이픈 문자를 놓습니다. 다음 식은 모든 소문자 및 하이픈을 찾습니다.
[-a-z]
[a-z-]

시작하는 문자 값이 하이픈보다 먼저 오고, 끝나는 문자 값이 하이픈과 같거나 나중에 오도록 범위를 만듭니다.
다음 두 정규식은 모두 이 요구 사항을 만족합니다.
[!--]
[!-~]

목록 시작에 캐럿 ^ 문자를 놓으면 목록이나 범위에 없는 모든 문자를 찾을 수도 있습니다.
목록에서 캐럿 문자가 다른 위치에 나타나면 이는 특별한 의미 없이 캐럿 문자 자체를 찾습니다.

다음 JScript 정규식은 장 제목의 숫자가 5보다 큰 경우를 찾습니다.

/Chapter [^12345]/

사실 위의 예제는 9번째 위치에 1,2,3,4,5를 제외한 모든 숫자와 문자를 찾습니다. 예를 들어, 'Chapter 7'과 'Chapter z'를 찾습니다.

하이픈 문자(-)를 사용하여 위와 동일한 식을 나타낼 수 있습니다.

/Chapter [^1-5]/


일반적으로 대괄호 식은 대소문자 또는 숫자 검색을 지정하기 위해 사용됩니다.

/[A-Za-z0-9]/



한정 기호
검색할 대상의 문자가 정확이 몇 개인지 모를 때도 있습니다.
이러한 불확실성을 해결하기 위해 정규식에서는 한정 기호의 개념을 지원합니다.
이러한 한정 기호를 사용하면 구성 요소가 몇 개 나타나야 검색이 참이 되는지를 지정할 수 있습니다.
한정 기호는 범위식 다음에 나타납니다.

아래 표에서는 다양한 한정 기호 및 그 의미를 설명합니다.

* 부분식의 선행 문자를 0개 이상 찾습니다.
예를 들어, 'zo*'는 "z" 와 "zoo"를 찾습니다. *는 {0,}와 같습니다.
+ 부분식의 선행 문자를 한 개 이상 찾습니다.
예를 들어, 'zo+'는 "zo" 및 "zoo"는 찾지만 "z"는 검색하지는 않습니다. +는 {1,}와 같습니다.
? 부분식의 선행 문자를 0개 이상 찾습니다.
예를 들어, 'do(es)?'는 "do" 또는 "does"의 "do"를 찾습니다. ?는 {0,1}과 같습니다.
{n} n은 음이 아닌 정수입니다. 정확하게 n 개 찾습니다.
예를 들어, 'o{2}'는 "Bob"의 'o'는 찾지 않지만 "food"의 o 두 개는 찾습니다.
{n,} n은 음이 아닌 정수입니다. 최소한 n 개 찾습니다.
예를 들어, 'o{2,}'는 "Bob"의 'o'는 찾지 않고 "foooood"의 o는 모두 찾습니다.
'o{1,}'는 'o+'와 같고 'o{0,}'는 'o*'와 같습니다.
{n,m} m 및 n은 음이 아닌 정수며 여기서 n <= m입니다. 최소한 n 개, 최대한 m개 찾습니다.
예를 들어, 'o{1,3}'은 "fooooood"의 처음 o 세 개를 찾습니다. 'o{0,1}'은 'o?'와 같습니다.
쉼표와 숫자 사이에는 공백을 넣을 수 없습니다.


연속된 숫자를 처리할 수 있는 방법도 필요하다.

/Chapter [1-9][0-9]*/

위 경우 한정 기호 *는 0과 9를 포함한 자리 수를 지정하는 범위식 [0-9]에 적용됩니다.

위 예제에서 + 또는 ? 한정기호가 사용되지 않은 이유는,
'+' 한정 기호는 두 번째 위치 또는 그 다음에 꼭 숫자가 올 필요가 없으므로 여기서 사용되지 않습니다.
'?' 문자도 번호를 두 자리 수로 제한하므로 사용되지 않습니다.

장 번호는 99장으로만 제한되므로 다음 JScript 식을 사용하여 적어도 한 자리 수를 지정할 수 있지만 두 자리 수 이상은 지정할 수 없습니다.

/Chapter [0-9]{1,2}/


위 식의 단점은 99보다 큰 장 번호가 있어도 처음 두 자리 수에 해당하는 장 번호만을 찾는다는 것입니다.
또한 누군가가 Chapter 0을 만들어도 그것까지 찾습니다. 두 자리 수만을 찾는 JScript 식은 아래 예를 사용하는 것이 좋습니다.

/Chapter [1-9][0-9]?/

또는 다음을 사용합니다.

/Chapter [1-9][0-9]{0,1}/


범위식에 일치하는 범위를 한정하려면 ? 를 사용한다

'*', '+' 및 '?' 한정 기호는 일치하는 범위가 무제한적이며 가능한 한 텍스트를 많이 찾습니다.
그러나 이렇게 많이 찾을 필요가 없는 경우도 있습니다. 즉, 최소한으로 찾아야 하는 경우도 있습니다.

예를 들어, HTML 문서에 다음과 같은 텍스트가 있고, H1 태그로 묶인 장 제목을 찾는다고 가정합니다.

<H1>Chapter 1 Introduction to Regular Expressions</H1>

다음 식은 여는 H1 태그에 있는 보다 작음 기호(<)에서 닫는 H1 태그 끝에 있는 보다 큼 기호(>) 사이에 있는 모든 문자열을 찾습니다.

/<.*>/

실제 검색하려는 문자열이 여는 H1 태그뿐인 경우에 다음 제한적인 식은 <H1>만 찾습니다.

/<.*?>/

'?'를 '*', '+' 또는 '?' 한정 기호 다음에 놓으면 식은 무제한적인 검색에서 제한적인 검색 또는 최소 검색으로 변환됩니다.



앵커
지금까지 예는 장 제목이 나타나는 위치를 찾는 작업에 관한 것이었습니다.
공백, 숫자가 이어지는 'Chapter' 문자열의 위치는 실제 장 제목이거나 다른 장에 대한 상호 참조일 수 있습니다.
실제로 장 제목은 항상 줄의 시작 위치에 있으므로
줄의 시작 위치에 있는 제목만 찾고 다른 위치에 있는 상호 참조는 찾지 않는 방법을 만들 수 있습니다.

앵커가 이러한 기능을 제공합니다. 앵커를 사용하면 정규식을 줄의 시작이나 끝 위치에 비교시킬 수 있습니다.
단어 내부 또는 단어 시작이나 끝에 나타나는 정규식을 만들 수도 있습니다.
다음 표는 정규식 앵커 및 그 의미를 보여줍니다.

앵커 설명

^ 입력 문자열의 시작 위치를 찾습니다.
Multiline 속성이 설정되어 있으면 ^는 '\n' 또는 '\r'앞의 위치를 찾습니다.
$ 입력 문자열의 끝 위치를 찾습니다.
Multiline 속성이 설정되어 있으면 '\n' 또는 '\r'뒤의 위치를 찾습니다.
\b 단어의 경계, 즉 단어와 공백 사이의 위치를 찾습니다.
예를 들어, 'er\b'는 "never"의 "er"는 찾지만 "verb"의 "er"는 찾지 않습니다.
\B 단어의 비경계를 찾습니다.
'er\B'는 "verb"의 "er"는 찾지만 "never"의 "er"는 찾지 않습니다.


앵커와 한정 기호는 함께 사용할 수 없습니다.
줄 바꿈 또는 단어 경계 전후 바로 다음에는 한 자리만 올 수 있으므로 '^*'와 같은 식은 허용되지 않습니다.

텍스트 줄의 시작 위치에 있는 텍스트를 찾으려면 정규식 시작에 ^ 문자를 사용합니다.
이것은 대괄호 식에서 사용하는 '^'와는 다릅니다.

텍스트 줄 끝에 있는 텍스트를 찾으려면 정규식 끝에 $ 문자를 사용하십시오.

장 제목을 찾을 때 다음 JScript 정규식에서처럼 앵커를 사용할 수 있습니다.
그러면 줄의 시작 위치에서 두 자리까지 장 제목을 찾습니다.

/^Chapter [1-9][0-9]{0,1}/

실제로 장 제목이 있는 줄에는 장 제목만 있으므로 장 제목은 줄의 시작 및 끝에 있어야 합니다.
다음 식에서 지정된 검색 문자열은 장만 찾고 상호 참조는 찾지 않습니다.
따라서 이 정규식은 텍스트 줄의 시작과 끝에서만 찾습니다.

/^Chapter [1-9][0-9]{0,1}$/

단어 경계를 찾는 방법은 약간 다르지만 정규식에 매우 중요한 기능을 추가합니다.
단어 경계는 단어와 공백 사이의 위치입니다.
비단어 경계는 그외 다른 위치입니다.
다음 JScript 식은 단어 'Chapter'의 처음 세 문자가 단어 경계 다음에 나타나므로 이 세 문자를 찾습니다.

/\bCha/

여기서 '\b' 연산자의 위치는 매우 중요합니다.
이 연산자가 검색할 문자열 앞에 올 경우 단어의 시작 부분에서 문자열을 찾고
검색할 문자열 뒤에 올 경우에는 단어의 끝 부분에서 문자열을 찾습니다.
예를 들어, 다음 식은 'ter'가 단어 경계 앞에 오므로 'Chapter'라는 단어에서 'ter'를 찾습니다.

/ter\b/

또는 다음과 같습니다.

다음 식은 'Chapter'의 'apt'를 찾지만 'aptitude'의 'apt는 찾지 않습니다.

/\Bapt/

또는 다음과 같습니다.

왜냐하면 'apt'는 'Chapter'라는 단어에서 비단어 경계에 있지만
'aptitude'라는 단어에서는 단어 경계에 있기 때문입니다.
비단어 경계 연산자의 경우 검색할 문자열이 단어 시작이나 끝과 관계가 없으므로 위치는 중요하지 않습니다.



대체 및 그룹화
대체 정규식은 '|' 문자를 사용하여 두 개 이상의 대안 중 하나를 선택할 수 있습니다.
대체 정규식을 사용하면 '|' 문자 양쪽의 식 중 가능한 가장 큰 식을 찾습니다.

장 제목 정규식을 확장하여 장 제목 이상의 것을 다루도록 할 수도 있으나 생각처럼 그리 간단하지는 않습니다.
다음 JScript 식이 줄의 시작과 끝에서 'Chapter' 또는 'Section' 다음에
한 자리 또는 두 자리 수가 나오는 문자열을 찾는다고 생각할 수 있습니다.

/^Chapter|Section [1-9][0-9]{0,1}$/

하지만 위의 정규식은 줄 첫부분에 나오는 'Chapter' 또는 줄 끝에 나오는 'Section'과
다음에 모든 수가 오는 경우를 찾습니다.

입력 문자열이 'Chapter 22'일 경우 위의 식은 단어 'Chapter'만 찾고
입력 문자열이 'Section 22'일 경우 식은 'Section 22'를 찾습니다.
그러나 이 정규식은 의도했던 것과는 다르므로 사용자의 의도에 맞는 결과가 나올 수 있는 정규식을 만들어 보겠습니다.

괄호를 사용하여 대체 범위를 제한할 수 있습니다. 즉, 두 단어 'Chapter'와 'Section'만 적용되도록 제한합니다.
그러나 나중에 부분식에 대한 절에서 설명하겠지만, 괄호는 부분식을 만들 때도 사용되므로 그 사용 방법이 까다롭습니다.
위의 정규식에서 적합한 위치에 괄호를 추가하면 'Chapter 1' 또는 'Section 3'과 같은 문자열을 찾는 정규식을 만들 수 있습니다.

다음 정규식은 괄호를 사용하여 'Chapter' 및 'Section'을 그룹화했으므로 식이 제대로 작동하게 됩니다.

/^(Chapter|Section) [1-9][0-9]{0,1}$/

이 식은 제대로 작동하지만 예기치 않은 결과가 발생하기도 합니다.
'Chapter|Section' 앞뒤로 괄호를 넣으면 적절하게 그룹화되고,
이 두 단어 중 하나는 나중에 사용할 수 있도록 캡처됩니다.
위의 식에는 괄호 쌍이 하나뿐이므로 부분 검색 문자열이 하나만 캡처됩니다.
이 부분 검색 문자열은 JScript에 있는 RegExp 개체의 $1-$9 속성을 사용하여 참조할 수 있습니다.

부분 검색 문자열을 캡처하는 것이 바람직할 때도 있고 그렇지 않을 때도 있습니다.
위의 예제에서 실제로 하려는 작업은 괄호를 사용하여
단어 'Chapter' 또는 'Section' 중 선택한 것을 그룹화하는 것입니다.
검색한 문자열을 나중에 참조할 필요는 없습니다.
사실, 부분 검색 문자열을 캡처할 필요가 없으면 이를 사용하지 마십시오.
그러면 정규식에서 이런 문자열을 저장하기 위해 시간과 메모리를 사용하지 않아도 되므로 효율성이 높아집니다.

괄호 안에서 정규식 패턴 앞에 ''?:'를 사용하면 나중에 사용하도록 문자열을 저장하지 않습니다.
다음 예는 위의 정규식을 수정한 것으로, 부분 검색 문자열을 저장하지 않으면서 동일한 기능을 합니다.


/^(?:Chapter|Section) [1-9][0-9]{0,1}$/

?: 메타문자 외에도 예상 검색에 사용하는 기타 비캡처 메타문자가 두 가지 있습니다.
?= 로 지정된 포함 예상 검색은 괄호 안의 정규식 패턴과 일치하는 문자열이 시작되는 곳에서 문자열을 검색합니다.
?! 로 지정된 제외 예상 검색은 정규식과 일치하지 않는 문자열이 시작되는 곳에서 문자열을 검색합니다.

예를 들어, Windows 3.1, Windows 95, Windows 98 및 Windows NT에 대한 참조가 들어 있는 문서가 있습니다.
Windows 95, Windows 98 및 Windows NT에 대한 모든 참조를 찾고
이러한 참조를 Windows 2000으로 변경하여 문서를 업데이트해야 한다고 가정합니다.
다음 JScript 정규식은 포함 예상 검색의 예를 보여주고 있으며 Windows 95, Windows 98 및Windows NT를 찾습니다.

/Windows(?=95 |98 |NT )/

일단 문자열을 찾으면 예상 문자열에 포함된 문자를 제외하고 검색된 텍스트 바로 다음부터 찾기 시작합니다.
예를 들어, 위의 정규식이 'Windows 98'을 찾으면 '98' 다음이 아닌 'Windows' 다음부터 다시 찾습니다.



역참조
정규식의 가장 중요한 기능 중 하나는 나중에 사용하도록 검색된 패턴의 일부를 저장하는 기능입니다.
앞에서 설명했듯이 정규식 패턴 또는 패턴의 일부를 괄호로 묶으면 그 식의 일부를 임시 버퍼에 저장할 수 있습니다.
이와는 반대로 비캡처 메타문자인 '?:', '?=' 또는 '?!'를 사용하여 저장된 정규식 일부를 무시할 수 있습니다.

캡처된 각 부분 검색 문자열은 정규식 패턴에서 왼쪽에서 오른쪽으로 저장됩니다.
부분 검색 문자열이 저장되는 버퍼 번호는 1부터 시작해서 최대 99개의 부분식까지 저장할 수 있습니다.
서로 다른 버퍼는 '\n'을 사용하여 액세스할 수 있는데 여기서 n은 특정 버퍼를 식별하는 한 자리 또는 두 자리의 십진수입니다.

가장 간단하고 가장 유용한 역참조 응용 프로그램 중 하나는 텍스트에서 동일한 두 단어를 찾는 기능을 제공합니다.
다음 문장을 살펴 보십시오.

Is is the cost of of gasoline going up up?

위 문장의 문제는 단어가 중복되어 있다는 것입니다.
모든 단어마다 일일이 중복 여부를 검사하지 않고 그 문장을 수정하는 방법을 개발하면 좋을 것입니다.
다음 JScript 정규식은 단일 부분식을 사용하여 이 문제를 해결합니다.

/\b([a-z]+) \1\b/gi

이 경우 괄호 안의 모든 요소가 부분식이 됩니다.
캡처된 식에는 '[a-z]+'에 지정된 대로 영문자를 하나 이상 포함하고 있습니다.
정규식의 두 번째 부분은 이전에 캡처된 부분 검색 문자열에 대한 참조입니다.
즉, 대괄호 식에서 검색된 단어가 연달아 나타나는 경우입니다.
'\1'을 사용하여 지정된 첫 번째 부분 검색 문자열을 지정합니다.
단어 경계 메타문자는 구분된 단어만 검색합니다.
그렇게 하지 않으면 이 식에서 "is issued" 또는 "this is"와 같은 구가 제대로 식별되지 않습니다.

JScript 식에서 정규식 다음에 오는 전역 플래그('g')는
입력 문자열에서 찾을 수 있는 가능한 한 많은 검색할 문자열에 식이 적용됨을 나타냅니다.
식 끝의 대소문자 구분 안함('i') 플래그는 대소문자를 구분하지 않도록 지정합니다.
여러 줄 플래그는 줄 바꿈 문자 양쪽에 잠재적으로 검색할 문자열이 있을 수 있음을 지정합니다.

위의 정규식을 사용하면 다음 JScript 코드로 부분 검색 문자열 정보를 사용하여
텍스트의 문자열에 연속으로 나오는 동일한 두 단어를 한 단어로 바꿀 수 있습니다.

var ss = "Is is the cost of of gasoline going up up?.\n";
var re = /\b([a-z]+) \1\b/gim; //정규식 패턴을 만듭니다.
var rv = ss.replace(re,"$1"); //두 단어를 한 단어로 바꿉니다.


replace 메서드에서 $1을 사용하면 처음 저장된 부분 검색 문자열을 참조합니다.
부분 검색 문자열이 하나 이상 있으면 이를 $2, $3 등을 사용하여 계속 참조할 수 있습니다.

역참조를 사용하는 또 다른 사례는 URI를 각 구성 요소로 나누는 것입니다.
다음 URI를 프로토콜(ftp, http 등), 도메인 주소 및 페이지/경로로 나눌 수 있습니다.

http://msdn.microsoft.com:80/scripting/default.htm

다음 정규식은 그 기능을 제공합니다. JScript의 경우는 다음과 같습니다.

/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/


괄호로 묶은 첫 번째 부분식은 웹 주소의 프로토콜 부분을 캡처하도록 설계되었습니다.
이 부분식은 콜론과 두 개의 슬래시 앞에 오는 단어를 모두 찾습니다.
괄호로 묶은 두 번째 부분식은 주소 중 도메인 주소 부분을 캡처합니다.
이 부분식은 '/' 또는 ':' 문자를 포함하지 않는 문자 시퀀스를 찾습니다.
괄호로 묶은 세 번째 부분식은 웹 사이트 포트 번호가 지정되어 있으면 이를 캡처합니다.
이 부분식은 콜론 다음에 오는 0 이상의 자리 수를 찾습니다.
괄호로 묶은 네 번째 부분식은 웹 주소로 지정된 경로 및 / 또는 페이지 정보를 캡처합니다.
이 부분식은 '#' 또는 공백 문자를 제외한 하나 이상의 문자를 찾습니다.

정규식을 위의 URI에 적용하면 부분 검색 문자열에 다음이 포함됩니다.

RegExp.$1은 "http"를 포함합니다.

RegExp.$2는 "msdn.microsoft.com"을 포함합니다.

RegExp.$3은 ":80"을 포함합니다.

RegExp.$4는 "/scripting/default.htm"을 포함합니다.
원본출처:http://venture.inchon.ac.kr/ius_bbs/view.php?id=909&code=develop
사본출처: http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=35975&sca=&sfl=wr_subject%7C%7Cwr_content&stx=%BF%AA%C2%FC%C1%B6&sop=and

 요즘 소셜커머스에보면 잔여시간 하면서 막 나오잔아요... ^^;
 간단하게 구현해본 타이머 기능입니다.

간단한 소스니까 응용해서 사용하시면 좋을것 같습니다...


 $(document).ready(function() {

  // 총 남은시간 갱신
  var timeLeft = 500; // 초 단위
  
  var num = function(str)
  {
   if(str<10)
    return '0'+str;
   else
    return str;
  }

  var updateLeftTime = function() {
   timeLeft = (timeLeft <= 0) ? 0 : -- timeLeft;
   
   var hours = num(Math.floor(timeLeft / 3600));
   var minutes = num(Math.floor((timeLeft - 3600 * hours) / 60));
   var seconds = num(timeLeft % 60);
    
   $('#t_left_time').html(hours+':'+minutes+':'+seconds);
  }  

  updateLeftTime();
  setInterval(updateLeftTime, 1000);

 });

<span id="t_left_time">00:00:00</span>

 jQuery 동영상 강의 입니다...

 

 외쿡 사람이라 외쿡 말로 진행됩니다만,

 한편한편이 짧아서 지루하지가 않고...

 쉽게 잘 설명하네요... ( 영어는 잘 모르지만... ^^ )

 

해당 강좌의 소스까지 있으니 많은 도움이 되리라 생각됩니다...

 

  • Day 1
  • Day 2
  • Day 3
  • Day 4
  • Day 5
  • Day 6
  • Day 7
  • Day 8
  • Day 9
  • Day 10
  • Day 11
  • Day 12
  • Day 13
  • Day 14
  • Day 15
  • New Audio Components for Delphi...

     

    사용하기 굉장히 쉽고 직관적이며 다양한 오디오 포멧을 지원하고 있습니다...

    Delphi 2010에서도 무리없이 잘 돌아가는것을 확인하였습니다....

     

    더 좋은건....

    무료! 라는것.... 클클...

     

    http://www.symmetrica.net/newac/ 

    사이트에서 자세한 설명과 다운로드 받으실수 있습니다....

     

    Short feature description:

    • Audio recording and playback using DirectSound
    • Audio recording and playback using low latency ASIO drivers
    • CD-ripping
    • Supported formats: wav, Ogg Vorbis, FLAC, Monkey Audio, WavPack, MP3, Windows WMA, DTS, AC-3, AAC, TTA, OptimFROG, TAK, Musepack 
    • Sound mixing, concatenation, cutting and insertion of audio fragments.
    • Audio resampling
    • 8, 16, 24, 32 bit sound support
    • Multi-channel sound
    • Id3v*, Ape, Vorbis tags support
    • Ready for Delphi 2009
    • License: NewAC is free for both open source and commercial use

     

    오랫만의 포스팅이네요...

     

    이번에 공개 해드릴것은 Desktop Linker 란 ocx 파일입니다...

    자신에 사이트에 방문하면 자동으로 사용자 바탕화면에 바로가기 아이콘을 만들어 줍니다...

     

    아마 온라인 게임 설치하시면 바탕화면에 깔리는거... 바로 그겁니다...

    이러한 형태로 만들어 지구요

    ActiveX 용으로 만들어 졌습니다...

     

    ocx파일을 웹에서 사용하시려면 프로그램 인증서를 먹이셔야 합니다...

    그렇기 않으면 ocx파일이 설치되지 않아요.... 인증서 가격은 1년 20만원대 였던걸로 기억이 납니다.

    인터넷 검색하셔서 갠찬은곳에서 구입하신후 사용하시면 됩니다.. 우선 예제 보시죠...

     

     

    http://test.love2u.be/20100817/

    테스트후에는
      인터넷 브라우져 -> 도구 -> 인터넷옵션 -> 설정 -> 개체보기 에서
    Desktop_linker.ocx 를 삭제해 주세요.
      그렇지 않으면 배포버젼과 classid가 같아서 작동이 되지 않을수 있습니다.


    우선 예제 페이지의 ocx에는 제가 가지고있는 인증서를 먹였습니다.

    예제용에는 무단도용 카피(?)루틴이 걸려 있으므로 훔쳐갈 생각은 하지 마세요.. ^^;

     

    사용법은 간단합니다.

    원하시는 페이지에

     

    오브젝트를 삽입하시고 ocx경로를 마추어 줍니다.

    그리고 자바스크립트로 첫번쨰는 사이트 url을 두번째로는 생성될 아이콘 이름을 넣어주시면 됩니다.

    <OBJECT classid="clsid:CF41BD83-1A4D-4F89-942F-63F0E5E41834" codebase="Desktop_linker.ocx" width=0 height=0 align=center hspace=0 vspace=0 id=Linker></OBJECT>
    <script type="text/javascript">
    <!--
     Linker.SendUrl('http://www.love2u.be','Love2u로 오세요!');
    //-->
    </script>

     

     위에 파일을 다운받으시면 됩니다...

     

    다른곳에는 올리지 말아주세요...

    대충 만든거라 좀 창피하군요.. 딴곳에다가 올리면 고발할겁니다.. ^^;

     

    다시한번 말씀드리지만 배포용 파일에는 인증서가 먹여져있지 않습니다.

    따라서 정상적으로 돌리시려면 따로 구입하셔야 합니다.

    ( 제가 파는게 아니라 인증기관에서 구입하셔야 해요... )

     

    아이콘은 \system32\SHELL32.dll 의 13번째 아이콘을 사용했습니다.

    따라서 OS마다 아이콘이 다르게 나올수 있구요...

    현재 버젼에서는 아이콘을 원하는걸로 바꾸실수 없습니다... ^^;

     

    수정 요청이나 개선 요청은 따로 받지 않겠습니다...

    그럼 즐프 하세요~ ^^;

     

    1. 이현진 2011.05.17 12:17 신고

      안녕하세요.
      이거 쓰고 싶은데요...
      어떤 인증서를 받아야 하는건가요?
      15만원부터 있던데 제일 싼거 서도 되는건가요??
      그리고, 인증서 설치는 어떻게 하는건가요??

      • Dexter Park 박용섭 2011.06.24 10:18 신고

        답변이 늦었습니다.
        "ActiveX 인증서"로 검색하셔서 구입하시면 됩니다.
        인증서 설치는 대부분 판매 사이트에서 자세히 기술하고 있으니 참고하시면 됩니다. ^^

    프로그래머들에게 가장 짜증나게 하는게 바로 폼체크가 아닌가 생각됩니다.

    사실 간단한듯 하면서도 짜증나서 예전에 만들어놓은거 대충 가져다 쓰는중이었습니다.

     

    새로이 프로젝트를 진행하면서 기존 '아이디 중복체크' 버튼등을 빼고싶다는 생각이 들었습니다.

    관련 자료를 찾아보니 J-Query Plugin 중에 Validation라는 것이 있더군요.

    ( 관련자료 : http://docs.jquery.com/Plugins/Validation )

     

    그러나 한국에서는 약간 맞지 않은게 보였습니다.

    맞지 않다기보다 지원하지 않는 것이랄까요?

    그래서 필요한 기능을 플러그인에 추가해 넣기로 했습니다.

     

    제가 필요한것은

     

    1. 한글만 입력가능
    2. 영문만 입력가능
    3. 한글 및 영문만 입력가능
    4. 주민번호 유효성 체크
    5. 사업자번호 유효성 체크


     

    위 5가지 정도였습니다.

     

    일단 구현 예제부터 확인해보시길 바랍니다..

     

    http://test.love2u.be/20100408/

     

    소스를 보시면 아시겠지만 굉장히 간단하게 구현이 되어있습니다.

    한번의 작업으로 편하게 할수 있게 되었군요...

     

    J-Query는 따로 받으시면 되구요.

    수정된 플러그인은 이걸 받으시면 됩니다.

     

    일단 사용하시려면 해당페이지에

    J-Query와 Validation 플러그인을 넣으셔야 합니다.

     

    이런식으로 넣으면 되요.. ^^;

    <script type="text/javascript" src="/js/jquery-1.4.2.min.js"></script>
    <script type="text/javascript" src="/js/jquery.validate.js"></script>


     

    사용하실때는 기본적인 J-Query 문법을 따릅니다.

     

      $(document).ready(function() {

       $("#form").validate({
        rules: {
         id:{required: true,minlength: 4,remote: {type:"post", url:"/20100408/check_id.php"}}    },

        messages: {
         id: {required: "아이디를 입력하시오",minlength: jQuery.format("{0}자 이상"),remote: "이미 등록된 아이디"}
        }

       });
      });


     

    rules에 기본적인 규칙들을 넣으시면 되요..

    required: true 란 필수항목이란 것이구요.

    minlength: 4 란건 최소길이 4자 라는 겁니다.

     

    룰은 이것말고도 많이 있는데요.

    여기선 다 다루지 않겠구요.

    http://docs.jquery.com/Plugins/Validation

    여기 가시면 자세하게 나와있습니다.

    영문이긴 하지만 자세히보면 너무 쉬운 영어들이예요.

    영어에 문외한인 저도 알아보니까요... ^^;

     

    위 소스에서 유의해서 보실 부분은 remote 란 부분인데요.

    remote 뒷부분인 url에 /20100408/check_id.php이곳으로 데이터를 post 방식으로 보내게 됩니다.

     

    그리고 messages 은 해당 조건에 만족하지 못할때 뿌려지는 메세지 입니다..

    쉽죠??

     

    check_id.php 에서는 true 와 false 로 응답을 해주시면 되는데요...

     

    <?
     if($_POST['id']=="dexter" or $_POST['id']=="love2u" or $_POST['id']=="guest") echo 'false';
     else echo 'true';
    ?>


     

    일단 저는 이렇게 적용하였습니다.

    Sql과 연동하셔서 처리하시면 실시간 중복 체크가 완성이 되겠지요??

    POST로 보냈기 때문에 $_POST로 받았습니다...

     

    음.... 역시 전 누구를 가르킬 체질이 안되나 봅니다... --;

    어떻게 설명해야할지 감이 잘 안서네요.. ^^;;;

     

    머 이런식으로 사용하심 되구요... ( 너무 대충 넘어가나요?? ^^; )

    그냥 예제 소스를 올리겠습니다...

     

     

     

    음...jquery.validate.js 파일의 수정 부분을 간단하게 설명해 볼께요...

    사실 그냥 사용하시려면 아래는 안보셔도 되요....

    우선 추가한 부분은 제가올린 소스 기준으로 245번째 줄을 보면

     

      kor: "한글만 입력가능합니다.",
      eng: "영문만 입력가능합니다.",
      kor_eng: "한글과 영문만 입력가능합니다.",
      ssn: "주민번호가 바르지 않습니다.",
      bssn: "사업자번호가 바르지 않습니다.",
      number: "번호만 입력 가능합니다.",


     

    messages안의 부분이있습니다.

    저 위의 rules에서 볼때  messages 에서 설정이 안되어있으면 나올 메세지 입니다.

     

    724~728줄에 classRuleSettings 을 지정 하였구요...

     

    1000번째 줄에 보면

    kor: function(value, element) {
       return this.optional(element) || /^[가-힣]+$/.test(value);
      },

     

    는 한글만 체크하기 위해 정규식을 썻구요...

    그 아래 eng,kor_eng 도 마찬가지구요...

     

    그리고 이건 주민번호 체크와 사업자번호를 체크하기위해 넣었습니다.


      ssn: function(value, element) {

       value = value.replace("-", "");
       
       if (/[^0-9-]+/.test(value))
        return false;

       var ssnCheck = 0;
       for (var i = 0; i < 12; i++) {
        ssnCheck += (i % 8 + 2) * value.charAt(i);
       }
       ssnCheck = (11 - ssnCheck % 11) % 10;

       if(ssnCheck != value.charAt(12)) {    
        return false;
       }

       return true;
      },      

      bssn: function(value, element) {

       value = value.replace("-", "");
       value = value.replace("-", "");
       
       var sum = 0;
       var getlist =new Array(10);
       var chkvalue =new Array("1","3","7","1","3","7","1","3","5");
       for(var i=0; i<10; i++) { getlist[i] = value.substring(i, i+1); }
       for(var i=0; i<9; i++) { sum += getlist[i]*chkvalue[i]; }
       sum = sum + parseInt((getlist[8]*5)/10);
       sidliy = sum % 10;
       sidchk = 0;
       if(sidliy != 0) { sidchk = 10 - sidliy; }
       else { sidchk = 0; }
       if(sidchk != getlist[9]) {
        return false;
       }
       return true;
      },

     

    지금까지 설명드린 나중에 rules에 추가해서 사용하실 수 있도록 한것입니다.

     

    일단 소스를 찬찬히 보시면 답이 튀어 나올듯 합니다...

    제 글을 읽어주실 분들이 어떤분들인지 모르니 어떻게 설명을 드려야 할지 모르겠네요...

    너무 깊숙히 접근하면 내용이 너무 길어질것같고 대충 적으면 성의 없어보이고...

     

    그냥 사용하시다가 궁굼하거나 막히는게 있으시면 아래 댓글을 달아주세요...

    그럼 답변 드리도록 하겠습니다.. 그게 좋겠져?? ^^;

     

    대단한것도 아니고 어려운것도 아닙니다...

    당장 모르신다고해도 천천히 보시면 다 이해 가시리라 믿습니다...

     

    별것도 아닌걸 포스팅했는지도 모르겠네요...

    어째든 어느분에겐 도움이 되었으면 합니다... ^^;

    끝으로 포스팅을 해야겠다는 자극을 주신 일현님께도 감사를... ^^;

     

    퍼가실땐 출처를 남겨주세요~~ ^^;

     

     

    1. defle 2010.05.04 22:23 신고

      꼭 필요한 건 다 말씀하신거 같네요. ^^

      좋은 내용 감사합니다.

    2. 드렁크수달 2010.05.10 04:51 신고

      좋은글 감사합니다. 정규식 내용만 퍼갑니다. ^^ 혹시 일현님이 그누보드에 일현님은 아시겠지요? ㅎㅎ;;

    3. 오호 2010.07.12 18:05 신고

      오호 감사합니다. ^^

    4. 질문자 2010.08.11 16:17 신고

      먼저 좋은글 감사드립니다
      validate 의 정규식에서 한글/한글_영문에 오류가 있어 문의를 드릴려고 합니다
      charset=euc-kr 에서 올려주신 파일을 적용하니
      "잘못된 범주의 문자집합입니다" 라고 뜨는데 혹시 해결 방법이 있는가 싶어
      글을 올립니다..;;
      글을 보시면 답변 부탁드립니다...

      • Dexter.Park 2010.08.17 21:25 신고

        euckr은 송수신시 문제가 생기는걸로 알고있습니다.
        euckr에서 사용하시려면 utf8로 변경하신후 보내셔야 합니다.

    5. 나이유미 2010.11.30 21:09 신고

      정말 감사합니다. 꾸벅 (__);

    6. 나그네 2011.03.09 17:33 신고

      그런데 jquery 1.5 에서는 잘 안되는군요..

      • Dexter Park 박용섭 2011.11.21 15:18 신고

        버젼 1.4.2때 만들었구요.
        1.6.2 에서 테스트 해보았으나 정상적으로 작동하고 있습니다.

    7. 누시 2011.12.08 20:36 신고

      감사합니다. 몇일을 고생 고생하다가 제가 원하는것을 찾았습니다. 꾸뻑
      이리도 자세히 적어주셔서 정말로 감사합니다.
      다름이 아니라 지금 아이디에 조건을 더 넣을려고 합니다.
      예를 들어 영문과 숫자만 그리고 중간에 공백 불허 등등을 더 넣을려고 하는데요 조건을 더 넣을려면 어떻게 해야 할까요?
      그리고 처음부터 조건을 명시하는 문구가 나와 있었음 하는데요.....
      마지막으로 성공을 했을때 오케이 아이콘 다음에 문구를 넣고 싶습니다.
      너무나 초보적인 질문 드려서 죄송합니다.
      다시금 좋은 소스 주셔서 정말로 감사히 잘 쓰겠습니다.

    일단 소스 코드 입니다.

     

    <?
    function hide_email($email) {
     $character_set = '+-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
     $key = str_shuffle($character_set);
     $cipher_text = '';
     $id = 'e'.rand(1,999999999);
     for ($i=0;$i<strlen($email);$i+=1)
     $cipher_text.= $key[strpos($character_set,$email[$i])];
     
     $script = 'var a="'.$key.'";var b=a.split("").sort().join("");var c="'.$cipher_text.'";var d="";';
     $script.= 'for(var e=0;e<c.length;e++)d+=b.charAt(a.indexOf(c.charAt(e)));';
     $script.= 'document.getElementById("'.$id.'").innerHTML="<a href=\\"mailto:"+d+"\\">"+d+"</a>"';
     $script = "eval(\"".str_replace(array("\\",'"'),array("\\\\",'\"'), $script)."\")";
     $script = '<script type="text/javascript">/*<![CDATA[*/'.$script.'/*]]>*/</script>';
     
     return '<span id="'.$id.'">[javascript protected email address]</span>'.$script;
    }
    ?>


     

    사용법은

     

    echo hide_email('test@test.com');

    이런식으로 사용하시면 됩니다...

    소스보기를 하여 보면...

     

    <SPAN id=e76655641>[javascript protected email address]</SPAN>
    <SCRIPT type=text/javascript>/*<![CDATA[*/eval("var a=\"6tbK5NHCsqFGf12wP9oe@IcJBVkL3mOiTavSdMDg+.jA_RWY-8pyxzXZhErunl470UQ\";var b=a.split(\"\").sort().join(\"\");var c=\"nRun1nRunbAZz\";var d=\"\";for(var e=0;e<c.length;e++)d+=b.charAt(a.indexOf(c.charAt(e)));document.getElementById(\"e76655641\").innerHTML=\"<a href=\\\"mailto:\"+d+\"\\\">\"+d+\"</a>\"")/*]]>*/</SCRIPT>


    이런 식으로 자동 수집기가 수집이 불가능한 형태로 보여집니다..

     

    출처 : http://www.maurits.vdschee.nl/php_hide_email/

     

    + Recent posts

    티스토리 툴바