시소당
2005년 2월 1일
독자 등급: 8.9
오는 장시간이었다, 그러나 java.util.regex 포장은 자바 1.4에 뜻깊고 거대하게 유용한 추가이었다. 일정하게 원본에 근거한 내용을 취급하는 웹 개발자를 위해, 이것은 중요한 생산력과 효율성 후원을 대표한다. 자바 정규식은 클라이언트 측 Java 애플릿과 또한 서버 측 J2EE와 JSP 부호에서 사용될 수 있다.
정규식 및 regex 포장을 사용하여, 당신은 쉽게 기술하고, 원본의 복잡한 본을 찾아내고 교묘히 다룰 수 있다. 나가 그것 없이 이제까지?" 곁에 얻은 방법 저를 의 이것 이다 명확하게 "신뢰하십시오 것의 종류.
나가 정규식의 뒤에 일반 아이디어를 설명할 이 기사에서 java.util.regex 포장이 어떻게 작동하는지, 설명하고십시오, 그 후에 얼핏 봄으로 정규식을 이용하기 위하여 끈 종류가 어떻게에 개조된지 위로 감싸십시오.
우리가 자바 regex API 자체의 세부사항으로 들어가기 전에, 무역에서 그들에 얼마나 정규식, 또는, "regex"가 있자, 실제로 인에 얼핏 봄이. 정규식이인 무슨 당신이 이미 알고 있는 경우에, 이 다음 섹션에 대충 훑어 보게 자유롭게 느끼십시오.
정규식은 무엇인가?
정규식은 당신이 본을 사용하여 원본에 있는 부분 문자열을 기술하는 것을 허용하는 오자 및 일련의 메타 문자이다. 이 메타 문자는 실제로 소형 언어를 형성한다. 실제로, 많은 방법으로, 당신은 자유로운 흐르는 원본을 위한 SQL 질문의 종류로 정규식을 생각할 수 있다. 뒤에 오는 문장을 고려하십시오:
나의 이름은 이고 나는 williamstown에서 산다.
우리는 어떻게", 에 관계 없이 위 원본의 모든 발생을 "찾아낼 수 있었는가 또는 소문자 "w" 사용되었다? 정규식으로 당신은 일련의 메타 문자 및 오자에게서 한 본을 구성해서 이 필요조건을 기술할 수 있다. 그런 본은 여기에서 있다:
[Ww] 악
이 자기의 매우 똑바른. 재미있는 부분은 [Ww] 분류이다 -- 부류 안에서 둘러싸인 편지의 아무 것나 (이 경우에는, 대문자 "W" 또는 소문자 "w") 수락가능하다는 것을 나타낸다. 이렇게, 대문자 소문자 w로 시작되는 원본이 이 정규식에 의하여 일치하고, 오자에 I, 그 후에 l, 그리고 그 후에 다른 l. 선행된다.
노치 높은 쪽으로 족답하자 그것. 의지의 2개의 발생이 상기 정규식에 의하여 실제로 일치할 것이다 -- 이름은 williamstown에 있는 원본의 첫번째 4개의 문자 의도한다. 우리는 의지와 의지 서만 그리고 간단하게 이 4개의 특성을 차례로 포함하는 낱말을 아닙니다 찾고 싶었다 있을지도 모른다. 개량한 버전은 여기에서 있다:
\ b [Ww] 악 \ b
\ b 우리가 워드 경계를 기술하는 방법 이다. 선의 공간, 탭 및 처음과 끝 점의 좋아하는 것이 워드 경계에 의하여 일치할 것이다. 이것은 성냥으로 효과적으로 williamtown에 있는 두번째 l가 워드 경계에 선행되지 않기 때문에 williamstown를 제외한다 -- 그것은 i.에 의해 따랐다.
나는 만드는 정규식의 순수 예술에 전체 기사를 바칠 수 있었다, 그러나 여기에서 나의 초점은 자바 정규식 포장 자체에 있다. 이렇게, 1개의 정규식을 시험하자 -- 우리는 기사의 나머지를 통하여 이 것으로 찌를 것이다.
(\ w+) @ (\ w+ \.)(\ w+) (\. \ w+)?
이 본 분석 분할하 그리고 정복 접근을 채택하자. (\ w+) 분류 (두번 나타난다 -- 것을 처음에는) 찾는다 \ w.에 의해 표시되는 것과 같이 낱말 특성을 시험하십시오. 한개 이상 낱말 특성이 나타나야 한ㄴ다는 것을 + 나타낸다 (필요하지 않게 동일한 것). 이것은 문자 @ 특성에 선행되어야 한다. 괄호는 실제로 여기에서 요구되지 않는다, 그러나 배치로 표정을 분할하고, 저것 논리적인 배치를 형성하는 것이 이와같이 극단적으로 유용할 다는 것을 당신은 곧 볼 것이다.
우리의 보기 regex의 이 첫번째 부분에 기초를 두어, (\ w+) @ 부분은, 여기에서 요구에 이제까지는 응하는 약간 보기이다:
billy@
joe@
francisfordcoppola@
다음 부분으로 따라 움직이자. (\ w+ \.) 분류는 유사하, 그러나 성냥을 만들기 위하여 따르도록 기간을 기대한다. 기간은 백슬래시를 사용하여 기간 특성 자체가 regex 메타 문자 (어떤 특성든지 일치하는) 자유패이기 때문에 도주되었다. 당신은 당신이 그들의 문자 의미에 어울리고 싶은 경우에 항상 메타 문자를 이와같이 도주해야 한다.
요구에 이제까지는 응할 약간 보기를 보자:
billy@webworld.
joe@optus.
francisfordcoppola@myisp.
(\ w+) 분류는 첫번째 분류와 동일하다 -- 그것은 한개 이상 낱말 특성을 찾는다. 당신이 이미 깨달아 확신한 대로 이렇게, 우리의 정규식은 이메일 주소와 일치하기 위하여 예정된다.
요구에 이제까지는 응하는 약간 보기:
billy@webworld.com
joe@optus.net
francisfordcoppola@myisp.com
우리는 거의 거기 있다. (\. \ w+) * 분류는 주로 이 때 이해되어야 한다 -- 우리는 한개 이상 낱말 특성에 선행된 기간을 찾고 있다. 그러나 * closing 괄호 후에 -로 무엇이인가? 정규식의 세계에서는, 우리는 * 선행하는 메타 문자, 오자 또는 그룹이 시간 더 0 또는 생길 다는 것을 표시하는 것을 사용한다. 0 또는 손가락 더에 선행된 낱말 특성이 한 예로, 에 의하여 \ w \ d* 일치할 것입니다. 우리의 보기에서는, 우리는 일련의 메타 문자를 함께 분류하기 위하여 괄호를, 그래서 이용한다 * 전체 그룹에게 적용한다. 이렇게, 당신은 해석할 수 있다 (\. * "한개 이상 낱말 특성을 거쳐 따른 기간 성냥으로 - \ w+), 그리고 성냥 조합 0 이상 시간".
완전한 정규식의 요구에 응하는 약간 보기:
fred@vianet.com
barney@comcorp.net.au
wilma@mjinteractive.iinet.net.au
우리의 정규식이 만들어진 상태에서, 그것은 것의 자바 측으로 위에 움직이는 시간 이다. 당신이 알 필요가 있을 맨처음 것은 자바 끈과 정규식 사이 오히려 불운한 통어론 충돌을 싸우는 방법 이다. 당신이 의 개발자, 취급해야 하는 충돌이다.
자바 안전한 정규식
경미하게 성가시다, 그러나 당신의 정규식을 자바 부호에 있는 사용을 위해 안전할 시키기 위하여 당신이 필요로 할 사실 유물이다. 이것은 어떤 백슬래시에 의하여 한계를 정한 메타 문자든지 도주될 필요가 있을 것이라는 점을 의미한다. 이것은 백슬래시 특성에는 자바에 있는 그것의 자신의 특별한 의미가 있기 때문이다. 이렇게, 우리의 보기 이메일 주소 regex는 다음과 같이 다시 쓰여야 할 것입니다:
끈 emailRegEx = "(\ \ w+) @ (\ \ w+ \ \.)(\ \. \ \ w+) (\ \ w+) *";
당신이 실제로 문자 백슬래시에 대하여 어울릴 필요가 있는 경우에, 당신은 위로 그러나 다시 두배로 해야 한ㄴ다는 것을 명심하십시오. 자바 안전한 regex를 읽는 것은 곤란할 수 있다, 그래서 당신은 "일정한" 정규식 (아마 regregex?)를 만들고 첫째로 싶을 수도 있다 그리고 사본을 경편한 유지하십시오 -- 아마 부호 코멘트 안쪽에.
이렇게, 우리는 어떻게 모든 유용한 무언가를 달성하는 이것을 사용하는가? 특정 상황에서는, 당신은 () 끈 종류에 replaceAll () 직접적으로 간단하게 방법을과 같은 대체한다 부르골 -- 우리는 이 접근에 얼핏 봄을 나중에 가지고 갈 것이다. 그러나, 더 정교한 regex operatations를 위해, 객체 지향 접근을 채택해서 도움이 되어 당신은 멀리 더 나을 것이 일 것이다.
본 종류
상쾌하게 하는 무언가는 여기에서 있다: java.util.regex 포장은 단지 3개의 종류만 포함한다 -- 그리고 그것들중 하나는 예외이다! 당신이 예상하기 때문에, 쉽 에 배우 API를 위해 아주 만든다 이. regex 포장을 이용하기 위하여 당신이 일반적으로 따를 것입니다 3개 단계는 여기에서 있다:
1. 본 종류를 사용하여 당신의 regex 끈을 집계하십시오.
2. 확인 회로 목표를 얻기 위하여 본 종류를 이용하십시오.
3. 어떤 성냥든지에 얻기 위하여 확인 회로에 방법을 부르십시오.
우리는 확인 회로 종류를 다음 보고, 그러나 보기로 본 종류에 안으로 급강하하자. 이 종류는 당신이 당신의 정규식을 집계하게 한다 -- 이것은 다수 표적 끈 (에 의하여 효과적으로 효율성과 사용을 위해 그것을 당신이 집계한 정규식을 시험하고 싶은) 끈 낙관한다. 뒤에 오는 보기를 고려하십시오:
emailRegEx를 = "(\ \ w+) @ 묶으십시오 (\ \ w+ \ \.)(\ \. \ \ w+) (\ \ w+) *";
//는 본 목표에 참고를 집계하고 얻는다.
본 본 = Pattern.com 더미 (emailRegEx);
//는 확인 회로 목표를 얻는다 - 우리는 이 다음을 덮는다.
확인 회로 확인 회로 = pattern.matcher (emailRegEx);
본 목표가 본 종류의 공전을 통해 만회되었다 포획 주는 방법을 집계한다 -- 당신은 새로운을 사용하여 instantiate 본 목표 할 수 있지 않는다. 일단 당신은 본 목표가 있으면 당신은 확인 회로 목표에 참고를 얻기 위하여 그것을 이용할 수 있다. 우리는 확인 회로를 다음 본다.
확인 회로 종류
먼저, 나는 정규식이 자유로운 흐르는 원본을 위한 SQL 질문의 종류다는 것을 건의했다. 유례는 전체로 완전하지 않다, 그러나 때 regex API를 사용하고다 이 선에 따라서 생각할 것을 도울 수 있을. 당신이 Pattern.com 더미 (myRegEx)를 JDBC PreparedStatement의 종류인 것으로 생각하는 경우에, 당신은 본 종류 확인 회로 (targetString) 방법을 SQL 추려낸 계산서의 종류 생각할 수 있다. 뒤에 오는 부호를 공부하십시오:
//는 regex를 집계한다.
끈 regex = "(\ \ w+) @ (\ \ w+ \ \.)(\ \. \ \ w+) (\ \ w+) *";
본 본 = Pattern.com 더미 (regex);
//는 우리가 질문하는 것을 바라는 "표적" 끈을 창조한다.
targetString 끈 = "당신은 g_andy@example.com 또는 andy@example.net에 정보 더"를 얻기 위하여 저를 이메일을 보낼 수 있다;
//는 확인 회로를 표적 끈에 근거하 얻는다.
확인 회로 확인 회로 = pattern.matcher (targetString);
// 발견 모든 성냥.
동안에 (matcher.find ()) {
System.out.println ("성냥을 찾아냈다: " + matcher.group ());
System.out.println ("출발 장소: " + matcher.start ());
System.out.println ("끝 위치: " + matcher.end ());
}
여기에서 계속하는 약간 재미있는 것이 있다. 확인 회로 목표를 얻기 위하여 우리가 본 종류의 확인 회로 () 방법을 이용했다는 것을 첫째로 위로, 주의하십시오. 우리의 SQL 유례를 사용하여 이 목표는, 아직도, 유래 성냥이 붙드는 곳 이다 -- JDBC ResultSet를 생각하십시오. 기록은, 당연히, 우리의 정규식과 일치한 원본의 부분이다.
조건적으로 확인 회로 종류의 발견 () 방법의 결과에 근거하는 동안 루프 뛰기. 이 방법 분석하 충족될 만큼 의 우리 표적 끈 만들 성냥, 어떤 순간에 그것 돌려보내 진실하. 조심하십시오: 런타임에 던져지는 발견을 부르기 전에 확인 회로를 이용하는 어떤 시도든지 검사받지 않는 IllegalStateException () 귀착될 것이다.
우리의 동안 루프의 몸에서 우리는 확인 회로 종류의 그룹 () 방법을 사용하여 일치한 부분 문자열을 만회했다. 우리의 동안 루프는 두번 수행한다: 한 번 우리의 표적 끈에 있는 각 이메일 주소를 위해. 매번, 그것은 그룹 () 방법으로 돌려보내진 일치한 이메일 주소, 및 부분 문자열 위치 정보를 인쇄한다. 산출을 보십시오:
성냥을 찾아냈다: g_andy@example.com
출발 장소: 20
끝 위치: 38
성냥을 찾아냈다: andy@example.net
출발 장소: 42
끝 위치: 58
당신이 볼 수 있던 대로, 간단하게 확인 회로의 시작 () 및 끝 () 방법 일치한 부분 문자열이 표적 끈에서 어디 생기는지 알아내는 이용의 사정 이었다. 다음 위로, 그룹 () 방법에 면밀한 관찰.
이해 그룹
학구 당신으로, Matcher.group는 표적 끈에서 () 완전한 성냥을 만회할 것이다. 그러나 만약에 당신이 또한 일치한 원본의 일부, 또는 "소집단"에 관심 있으면 무엇? 우리의 전자 우편 보기에서는, 이메일 주소 및 사용자 이름 부분의 호스트 이름 부분을 추출하는 것이 바람직할지도 모른다. 루프 동안에 몬 우리의 확인 회로의 개정 버전 보십시오:
동안에 (matcher.find ()) {
System.out.println ("성냥을 찾아냈다: " + matcher.group (0) +
". 사용자 이름은" + 이다
matcher.group (1) + "와 ISP는" + 이다
matcher.group (2));
}
당신이 되부를지도 모르다 대로, 그룹은 당신의 본의 일부의 주위에 감싸인 괄호의 세트로 대표된다. 보기, 더 특정한 Matcher.group (0)에서 것과 같이 Matcher.group를 사용하여 () 또는, 있는 첫번째 그룹은, 전체 성냥을 대표한다. 더 그룹은 동일한 그룹 (int 색인) 방법을 사용하여 찾아낼 수 있다. 위 보기를 위한 산출은 여기에서 있다:
성냥을 찾아냈다: g_andy@example.com. 사용자 이름은 g_andy 이고 ISP는 보기이다.
성냥을 찾아냈다: andy@example.net. 사용자 이름은 andy 이고 ISP는 보기이다.
당신이 볼 수 있던 대로, 그룹 (1)는 이메일 주소 및 그룹 (2)의 사용자 이름 부분을 만회한다 ISP 부분을 만회한다. 당신의 자신의 정규식을 만들 때 그것은 당신까지, 당연히, 어떻게 당신 논리적으로 소집단 당신의 본 이다. 이 예제에서 작은 감독은 기간 자체가 그룹 (2)에 의해 돌려보내진 소집단의 한 부분으로 붙잡는다 이다!
소집단이 그들의 개통 괄호의 순서에 기초를 두었다는 것을 좌에서 우로 색인이 붙는는다는 것을 명심하십시오. 이것은 당신이 다른 그룹 안에 보금자리가 되는 그룹을 사용할 때 특히 중요하다.
본과 확인 회로 종류에 조금 더 많은 것
저것은 거의 이 아주 작고의 중핵, 그러나 아주 가능한, 자바 API이다. 그러나, 일단 당신은 기초로 실험하는 기회가 있으면 당신이로 봐야 하는 다른 약간 다양한 것들이 있다. 본 종류에는 당신이 그것에 두번째 논쟁으로 () 방법을 집계하는 이용할 수 있는 다수 깃발이 있다. 예를 들면, 당신은 regex 엔진을 케이스에 관계 없이 ASCII 문자와 일치하도록 말하도록 Pattern.CASE_INSENSITIVE를 이용할 수 있다.
Pattern.MULTILINE는 또 다른 유용한 것이다. 당신은 때때로 당신의 표적 끈이 부호의 일방 통행이 아니다는 것을 regex 엔진에게 말하고 싶을 것이다; 오히려, 그것은 그들의 자신의 종료 특성이 있는 몇몇 선에는 포함한다.
당신이 필요로 하는 경우에, 당신은 자바를 사용해서 다수 깃발을 결합할 수 있다 | (수직 막대기) 통신수. 예를 들면, 당신이 multiline를 가진 regex를 집계하고 싶 무신경 지원을 싸는 경우에, 당신은 뒤에 온 것 할 수 있었다:
Pattern.com 더미 (myRegEx, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
확인 회로 종류에는 다수 재미있는 방법이, 너무 있다: 언급이 끈 replaceAll에 의하여 (replacementString 끈)와 끈 replaceFirst (replacementString 끈)는, 특히, 여기에서 가치가 있다.
replaceAll () 방법은 보충 끈을 가지고 가고 그것으로 모든 성냥을 교환한다. replaceFirst () 방법은 아주 유사하다 그러나 의지이다 -- 당신은 그것을 짐작했다 -- 성냥의 단지 첫번째 발생을 대체하십시오. 뒤에 오는 부호 보십시오:
손가락으로 끝내는 "BBC" 낱말이 //에 의하여 일치한다.
thePattern 끈 = "bbc \ \ d";
//는 regex를 집계하고 대소문자 구별을 떨어져 전환한다.
본 본 = (, Pattern.CASE_INSENSITIVE thePattern) Pattern.com 더미;
// 표적 끈.
끈 표적 = "나는 bBC1와 BbC2를 보고 싶다 - ITV가 너무 좋다는 것을" 나는 가정한다;
//는 표적 끈을 위한 확인 회로를 얻는다.
확인 회로 확인 회로 = pattern.matcher (표적);
//는 BBC에 모든 참고를 밖으로 더럽힌다.
System.out.println (matcher.replaceAll ("xxxx"));
Here 산출:
나는 xxxx와 xxxx를 보고 싶다 - ITV가 역시 좋다는 것을 나는 가정한다
Backreferences
그것은 다른 중요한 regex 화제에 얼핏 봄을 가지고 가는 가치가 있다: backreferences. Backreferences는 regex 엔진이 수행하고 있는 동안 당신이 체포한 소집단에 접근하는 것을 허용한다. 기본적으로, 이것은 당신이 본의 뒤에 성냥의 앞 부분에서 소집단을 언급할 다는 것을 의미한다. 당신이 동일한 편지로 시작하고 끝낸 3 편지 낱말을 위해 표적 끈을 검열할 필요가 있었다고 상상하십시오 -- 와우, sos 의 미라, 것의 저 종류. 일을 할 본은 여기에서 있다:
(\ w) (\ w) (\ 1)
이 경우에는, (\ 1) 그룹은 본에서 한 첫번째 성냥에 backreference를 포함한다. 기본적으로, 세 번째는 이 위치에서만 특성이 같은 첫번째에 있는 특성이 그룹을 parenthesised 동일하만 때 그룹을 일치할 것이다 parenthesised. 당연히, 당신은 당신이 backreference를 두번째 그룹 원한 경우에 \ 1로 대용하기 위하여 \ 2 간단하게 하고자 했다. 그것은 간단하다, 그러나 많은 경우에, 거창하게 유용한.
확인 회로 목표의 보충 방법 (및 끈 종류의 대조물 또한) 보충 끈에 있는 backreferences를 하기를 위한 표기법을 지원한다. 그것은 백슬래시 대신에, 그러나 용도 달러 기호 같은 방식으로 작동한다. 이렇게, matcher.replaceAll ("
$2" 정규식의 두번째 소집단에 의해 일치한 가치로)는 표적 끈에 있는 모든 성냥을 교환할 것입니다.
끈 종류 RegEx 방법
나가 먼저 언급했다시피, 자바 끈 종류는 정규식을 이용하기 위하여 새롭게 했다. 당신은 간단한 케이스, 완전하게 끈 종류에 regex에 의하여 가능하게 된 방법을 직접적으로 불러서 regex API를 사용하여 우회에서, 할 수 있다 직접적으로. 유효한 5개의 그런 방법이 있다.
당신은 부울 논리 연산 성냥 (끈 regex) 빨리 특정한 본이 끈에 의하여 정확하게 일치하는지 결정하기 위하여 방법을 이용할 수 있다. string 적합하게 지명한 replaceFirst (끈 regex, 끈 보충)와 끈 replaceAll (끈 regex, 끈 보충)는 방법 당신이 빠르고 더러운 원본 보충을 하는 것을 허용한다. 그리고 마지막으로, 끈은 정규식에 근거한 부분 문자열로 [] (끈 regEx) 끈 [] 나누었다 (끈 regEx, int 한계) 방법을 시켰다 당신을 나누었다 끈을 나누고. 이 마지막 2개의 방법은, java.util.StringTokenizer 의 강력한 훨씬 더와 유사한 개념에 있다.
그것이 훨씬 더 regex API 및 객체 지향 접근을 사용하는, 많은 경우에, 이해된ㄴ다는 것을 명심하십시오. 이것을 위한 1가지의 이유는 그런 접근이 precompile 당신에게 당신의 정규식을 준다 이고 그 후에 다수 표적 끈의 맞은편에 그것을 사용한다. 또 다른 이유는 가능한 간단하게 훨씬 더이다 이다. 당신은 빨리 1개의 접근 정상을 언제의 걸림새를 선택하기 위하여 다른 사람 얻을 것이다.
희망이 있, 나는 당신에게 regex API에서 기선을 주고 그것에게 약간 심각한 고려하기 위하여 아직 이 강력한 공구를 발견할 것인 그들을 유혹했다. 빠른 끝: 복잡한 정규식을 만드는 것을 시도하는 귀중한 개발 시간의 시간을 낭비하지 말라 -- 그것은 이미 존재할지도 모른다. 그들의 전체 낱단을 자유롭게 이용할 수 있게 하는 장소의 많음이 www.regexlib.com와 같은 있다.
[출처] 자바 Regex API [SitePoint]|작성자 양군짱
http://blog.naver.com/yanggun7201?Redirect=Log&logNo=80033421965