2007. 6. 29. 15:56

정규표현식 기초

정규표현식의 기본 문법

 

정규표현식은 소프트웨어에 따라서 방식이나 지원 범위가 다를 있습니다.

 

^The”

"The" 시작하는 문자열

"of despair$"

"of despair" 끝나는 문자열

"^abc$"

"abc" 시작하고 "abc" 끝나는 문자열 ("abc" 라는 문자열도 해당됨)

"notice"

"notice" 들어 있는 문자열

 

"ab*"

a 다음에 b 0 이상 ("a", "ab", "abbb", )

"ab+"

a 다음에 b 1 이상 ("ab", "abbb", )

"ab?"

a 다음에 b 있거나 없거나 (ab 또는 a)

 

"ab{2}"

a 다음에 b 2 있는 문자열 ("abb")

"ab{2,}"

a 다음에 b 2 이상 ("abb", "abbbb", .)

"ab{3,5}"

a 다음에 b 3개에서 5 사이 ("abbb", "abbbb", 또는 "abbbbb")

 

'*', '+', '?' 각각 "{0,}", "{1,}", "{0,1}" 같습니다.

 

( ) 문자열을 묶음 처리할 사용

"a(bc)*"

a 다음에 “bc” 0 이상 (묶음 처리)

"a(bc){1,5}"

a 다음에 “bc” 1개에서 5 사이

 

"hi|hello"

"hi" "hello" 들어 있는 문자열

(응용) "(b|cd)ef"

"bef" 또는 "cdef"

(응용) "(a|b)*c"

a b 섞여서 여러번 나타나고 그뒤에 c 붙어있는 패턴

 

. ()

임의의 문자

ex) "^.{3}$"        3문자로만 되어 있는 문자열

 

[] 괄호 안에 있는 내용 임의의 문자

[] 안에서 첫문자로 ^ 쓰면 괄호 내용의 부정 괄호 안에 포함되지 않는 문자

"[ab]"

a 또는 b  ("a|b" 동일한 표현)

"[a-d]"

소문자 'a'에서 'd'까지 ("a|b|c|d"또는 "[abcd]" 동일)

(응용) "^[a-zA-Z]"

영문자로 시작하는 문자열

(응용) "[0-9]%"

% 문자 앞에 하나의 숫자가 붙어 있는 패턴

(응용) "%[^a-zA-Z]%"

% 문자 사이에 영문자가 없는 패턴

 

특수 문자 자체를 검색하기 사용하기

\^

^

 

\.

.

\[

[

 

\$

$

\(

(

 

\)

)

\|

|

 

\*

*

\+

+

 

\?

?

\{

{

 

\\

\

\n

줄넘김문자

 

\r

리턴문자

\w

알파벳과 _ (밑줄)

 

\W

알파벳과 _ 아닌

\s

공간

 

\S

공간이 아닌

\d

숫자

 

\D

숫자가 아닌

\b

단어와 단어 사이의 경계

 

\B

단어 사이의 경계가 아닌

\t

Tab문자

 

\xnn

16진수 nn 해당하는 문자

 

[ ] 안에서는 특수 문자가 모두 효력을 잃게 됩니다.

 

검색 + 치환 위한 하부식(부분식)

( ) 둘러싼 부분은 각각 하나의 덩어리로 취급해서, 검색시 ( ) 안에 해당되는 내용들을 변경할 내용에서 그대로 가져다 이용 있습니다. 검색된 각각의 ( )안에 해당되는 내용은 변경할 내용에서 $1, $2, .. 등으로 지정해서 있습니다.

예제) mp3파일 이름 바꾸기

검색 : (.*) - (.*)\.mp3   .* 길이에 상관없이 임의의 문자열, \.

치환 : $2 - $1.mp3     앞에서 검색한 ( )안에 해당되는 내용끼리 순서 바꾸기

ex) "제목 - 연주자.mp3"  Þ "연주자 - 제목.mp3"

앞에서 정의한 하부식을 다시 활용하기 (제가 잘못 이해한 것일 수도 있는데)

\n ( ) 하부식 중에서 n번째 하부식 가리킵니다.

예제) (.+)\1+

\1 되어 있으니까 첫번째 부분식 (.+) 가리킵니다. 내용을 해석하자면, 일단 (.+) 있으니까 이에 해당되는 내용을 찾고, \1+ 있으니까 첫번째 부분식 (.+) 똑같은 내용이 뒤에 1 이상 있는 문자열을 찾습니다.

예제) abab같은 문자열이 위에 해당되는데, 일단 (.+) 임의의 문자열 ab 찾고 뒤에 \1+ 첫번째 부분식을 다시 1 이상 있는 것을 찾으니까 뒤의 ab 이에 해당합니다.

 

변경자 검색 방식 변경

(?i)

대소문자 무시 (기본값)

(?-i)

대소문자 구분

(?g)

"greedy" 모드로 전환 (기본값)

(?-g)

"greedy" 모드 해제, 따라서 "+" "+?" 동일한 것으로 인식

 

2007. 6. 29. 15:56

정규표현식의 기본 문법

Basic Syntax of Regular Expressions (정규표현식의 기본 문법)

먼저 특수문자 '^'와 '$'를 살펴봅시다. 이 문자의 역할은 문자열의 시작과 끝을 의미합니다. 다음과 같은 해당 예를 들 수 있습니다.

"^The": "The"로 시작하는 문자열
"of despair$": "of despair"로 끝나는 문자열
"^abc$": "abc"로 시작하고 "abc"로 끝나는 문자열 ("abc" 라는 문자열도 해당됨)
"notice": "notice"가 들어 있는 문자열

마지막 예제에서 보듯이 이 두 개의 특수문자가 없는 패턴은 검사대상이 되는 문자열에 어떤 위치에서든지 들어 있음 의미합니다.

특수문자로는 '*', '+', '?'도 있습니다. 이 문자들은 어떤 문자의 반복에 관한 지정을 해주는 문자입니다. 각각 '0또는 그 이상', '1또는 그 이상', '0또는 1'을 의미합니다. 여기에 몇 가지 예제가 있습니다.

"ab*": a뒤에 0 이상의 b가 있는 문자열 ("a", "ab", "abbb", 등);
"ab+": 위와 동일 하지만 최소한 하나 이상의 b가 있어야 함 ("ab", "abbb", 등);
"ab?": b가 하나 있을 수도 있고 없을 수도 있음 (ab 또는 a)
"a?b+$": a가 있을 수도 있고 없을 수도 있으며 그뒤에 하나 이상의 b로 끝나는 문자열

{ }를 사용하면 반복되는 수를 영역으로 지정할 수 있습니다.

"ab{2}": a뒤에 2개의 b가 있는 문자열 ("abb");
"ab{2,}": a뒤에 최소한 2개 이상의 b가 있는 문자열 ("abb", "abbbb", 등.);
"ab{3,5}": a뒤에 3개에서 5개 사이의 b가 있는 문자열 ("abbb", "abbbb", 또는 "abbbbb").

{ }를 사용할 대는 반드시 첫 번째 숫자는 적어야 됨을 유의합니다. ((O) "{0,2}", (X) "{,2}"). 또한 '*', '+', '?'는 각각 "{0,}", "{1,}", "{0,1}"와 같습니다.

이제 ()를 사용해서 하나의 문자가 아닌 여러 문자를 지정하는 방법을 알아봅니다.

"a(bc)*": a 뒤에 "bc"가 0또는 그이상의 수만큼 있는 문자열
"a(bc){1,5}": a 뒤에 "bc."가 1에서 5번 들어 있는 문자열

또 다른 특수문자로는 OR 연산을 하는 '|'를 들 수 있습니다.

"hi|hello": "hi"나 "hello"가 들어 있는 문자열
"(b|cd)ef": "bef" 또는 "cdef"
"(a|b)*c": a와 b가 섞여서 여러번 나타나고 그뒤에 c가 붙어있는 패턴

'.' (period)는 어떤 한 문자를 의미합니다.

"a.[0-9]": a뒤에 한 문자와 숫자가 붙어 있는 패턴
"^.{3}$": 3문자로만 되어 있는 문자열

[]표현은 문자열의 해당 위치에 사용될 수 있는 문자를 표현하는데 사용합니다.

"[ab]": a또는 b ("a|b"와 동일한 표현);
"[a-d]": 소문자 'a'에서 'd'까지 ("a|b|c|d"또는 "[abcd]"와 동일);
"^[a-zA-Z]": 영문자로 시작하는 문자열
"[0-9]%": % 문자 앞에 하나의 문자가 붙어 있는 패턴
",[a-zA-Z0-9]$": 영문자, 숫자로 끝나는 문자열 패턴

[]에서 '^'를 표현의 가장 처음에 사용하면 나타나서는 안 되는 문자를 지정할 수 있습니다. (예> "%[^a-zA-Z]%" 두 % 사이에 영문자가 없는 패턴)

"^.[$()|*+?{"같은 특수 문자는 백슬레쉬('')를 사용해서 escape될 수 있습니다( 역자 주 : escape 이란 다른 말로 literal로 탈출한다라고 할 수 있습니다 즉 특수문자로 인식되지 않고 일반 문자로 인식되게 합니다). 사용하는 관점에서 보면 백슬레쉬도 PHP3의 문자열에서 escape되어야 하기 때문에 예를 들어 "($|?[0-9]+"같은 정규표현식은 ereg("($|?[0-9]+", $str) 와 같이 사용됩니다 (이 표현식은 무얼 검사하는 걸까요? ^^;(이건 역자가 한 말이 아닙니다))

하지만 []안에서는 특수문자가 모두 효력을 읽게 되기 때문에 이 법칙을 벗어남을 기억하세요 []안에서는 백슬레쉬를 포함한 모든 특수문자들이 그 힘을 읽습니다 (예> "[*+?{}.]"는 말그대로 '*', '', '+', '?', '{', '}', '.' 문자를 의미합니다. 그리고 regex man 페이지에 나오듯이 ']'문자 자체를 포함하려면 문자들 리스트의 첫 번째에 위치시킵니다('^'가 있으면 '^'뒤에). '-'를 포함하려면 첫 번째 또는 마지막 문자로 지정하고 '-'문자가 영역의 경계 (예> a에서 -까지)일 경우 영역지정 문자의 두 번째 경계로 지정([a--])합니다.

완벽한 설명을 하려면 대조 순서(collating sequences), 문자 클래스(character classes), 동일 클래스(equivalence classes)에 대해서도 다루어야 하지만 이 글에서는 별 상관관계가 없기 때문에 regex man 페이지를 참고하도록 합니다.

-Validating Money Strings (금액 문자열 검사하기)

ok 이제 우리는 여기서 배운 것을 뭔가 실질적인 것에 적용 시켜봅시다. 사용자가 입력한 금액을 검사하는 정규표현식에 대해 알아봅니다. 금액은 "10000.00" 와 "10,000.00", 와, 센트 없이, "10000" 와 "10,000" 이렇게 4가지 방법으로 사용됩니다. (역자주 : 달러와 센트 군요 蝁,.蝁)

다음 정규표현식을 기초로 시작해 봅시다.

^[1-9][0-9]*$

이 정규표현식은 0으로 시작하지 않는 어떠한 수인지를 검사합니다. 하지만 "0"도 통과되지 못합니다. 그래서 다음과 같이 수정합니다.

^(0|[1-9][0-9]*)$

말로 표현하면 "0 이거나 0으로 시작하지 않는 수"입니다. 이제 수 앞에 -부호도 사용할 수 있게 수정해 봅니다.

^(0|-?[1-9][0-9]*)$

이 뜻은 "0 이거나 -이 있을 수 있는 수이고 이 수는 0으로 시작하지 않는다"입니다. 이제 좀 느슨하게 하고 유저가 0으로 시작하는 수도 입력할 수 있도록 해봅니다. 금액에 필요없는 -부호도 없애버립니다. 그리고 선택사항인 소수점 부분 패턴도 넣어서 다음 정규표현식이 나옵니다.

^[0-9]+(.[0-9]+)?$

하이라이트된 부분은 소수점(.)이 항상 최소한 하나이상의 수와 붙어 있어야 함을 의미합니다. 그러므로 예를 들면 "10."은 통과되지 못하고 "10" 과 "10.2"는 통과합니다.

^[0-9]+(.[0-9]{2})?$

이제 소수점 뒤에 반드시 2개의 수가 붙어 있어야 합니다. 이게 너무 심하다 싶으면 다음과 같이 해서

^[0-9]+(.[0-9]{1,2})?$

소수점 뒤에 하나의 숫자만 올 수도 있게 합니다. 이제 1000단위를 구분하는 ','를 표현해 봅니다.

^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$

"1~3개의 숫자와 그 뒤에 ','와 3개의 숫자로 이루어진 부분이 0개 또는 그 이상이 붙어 있는 패턴". 쉽죠? 이제 ','도 선택사항(옵션:option)으로 만들어 봅니다.

^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$

이게 전부입니다. 여기서 '+'를 '*'로 바꾸면 빈 문자열도 통과되는 패턴이 됩니다. 함수호출할 때 백슬래쉬 문자 escape하는 것 (역자 : /를 //로) 잊지 마세요. 일단 문자열이 검사되어 지면 str_replace("," , "" , $money) 함수로 ','를 없애버리고 double로 형 변환을 해서 산술연산에도 사용할 수 있게 합니다.

- Validating E-mail Addresses (E-mail 주소 검사하기)

이제 e-mail 주소를 살펴봅시다. e-mail주소는 3부분으로 구성됩니다. : user 명(@왼쪽편에 있는 모든 것), '@', 그리고 서버명(나머지 부분들) user명은 대문자 또는 소문자와 숫자, '.' '-', '_'로 구성됩니다. '_'를 제외하면 서버명도 마찬가지입니다. user 명은 .으로 시작하거나 끝나지 않습니다. domain명도 마찬가지입니다. 또한 .이 연속으로 있을 수도 없고 . 사이에는 최소한 하나 이상의 문자가 있어야 합니다. 이제 user명 부분을 검사하는 정규표현식을 만들어 봅시다.

^[_a-zA-Z0-9-]+$

이 정규표현식은 아직 .을 지원하지 않습니다. 다음과 같이 수정합니다.

^[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*$

말로 하면 "최소한 하나의 유효한 문자(valid character)와 그 뒤에 .과 유효문자들로 구성된 부분이 0또는 그 이상이 있는 패턴"입니다.

좀 간단하게 하기 위해 이 정규표현식을 ereg()대신에 eregi()함수에 사용합니다. eregi()함수는 대소문자를 구분하지 않기 때문에 "a-z"와 "A-Z"같이 두 개의 영역을 지정하지 않아도 되는 이점이 있습니다.(둘 중 어떤 것이라도 상관없음)

^[_a-z0-9-]+(.[_a-z0-9-]+)*$

서버명의 경우 '_'만 제외하고는 동일합니다.
^[a-z0-9-]+(.[a-z0-9-]+)*$

이제 '@'를 중심으로 서로 붙여서 다음과 같이 만들어 냅니다.

^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$

- 기타 사용

Extracting Parts of a String (문자열의 일부분 잘라내기)

ereg()와 eregi()함수는 문자열에서 패턴에 해당되는 부분을 잘라내는 기능이 있습니다. (메뉴얼 참고) 예를 들면 path/URL 문자열에서 파일명을 잘라내고 싶은 경우 다음과 같은 코드가 필요할 것입니다.

ereg("([^/]*)$", $pathOrUrl, $regs);
echo $regs[1];

Advanced Replacing (치환의 발전된 형태)

ereg_replace() 와 eregi_replace()는 아주 유용한 함수입니다. 문자열에 있는 모든 문자를 ','로 구분한다고 가정해 봅시다. 다음과 같이 할 수 있습니다. (역자 : trim()함수는 문자열의 앞과 뒤에 있는 공백문자를 모두 제거하는 함수)

ereg_replace("[ nrt]+", ",", trim($str));

2007. 6. 29. 15:55

MySQL 4.1이상에서 character-set을 euckr로 모두 맞추기

이 자료는 database.sarang.net에서 이영진님께서 올린 자료입니다.

소스설치하지 않은 MySQL 4.1버전에서는(5.0포함)
아무리 default-character-set=euckr, 그리고 init connect = SET NAMES euckr 로 세팅해도 결국에
PHP에서 확인해보면 character set connection 부분과 character set results 부분이 Latin1로 설정되어 있는것을 확인할수 있습니다.
그렇게되면 결국에 모든 PHP스크립트에 set names euckr 쿼리를 날릴수밖에 없었는데요.
이제야 좀 해결이 된거 같습니다.
MySQL 데몬 시작할때 client-handshake를 무시하게 하면 되는것이었네요.
이렇게 데몬을 실행하시면 됩니다.
#mysqld_safe --default-character-set=euckr --skip-character-set-client-handshake &

데이터베이스를 시작하실때 --skip-character-set-client-handshake부분을 추가하셔서 실행하시던가, 아니면 /etc/init.d/mysql의 267라인쯤
$bindir/mysqld_safe --datadir=$datadir --pid-file=$server_pid_file >/def/null 2>&1 &
이 부분에 위의 옵션을 추가해주시면 됩니다.

테스트해본결과 텔넷으로도, MySQL-front에서도, PHPMyAdmin에서도 모든 환경이 euckr로 세팅된것을 확인할수 있었습니다.


윈도우용 Mysql 세팅은 이거네요.. 딴거 필요 없고 이거 한방이면 되네요..ㅋ
my.ini 에서

[mysqld]
character-set-client-handshake = FALSE

2007. 6. 29. 15:53

Ascii 특수문자

사용자 삽입 이미지