SSISO Community

시소당

java replaceAll 잘쓰기

Java  String  기본  메소드인  replaceAll의  경우  regexp를  쓸  수  있기때문에  간단한  스트링  변환  작업은

한줄로도  간단히  끝낼수  있다

  

그  응용중  하나를  살펴보면  url중  도메인만  뽑아내기

하려는  내용은  url을  입력받아서  해당  도메인만  뽑아내는  작업이다.

    

String  referer  =  "http://name.siren24.com/servlet/name_check";

referer  =  referer.replaceAll("(?i:https?://([^/]+)/.*)",  "$1");

assertEquals(referer,  "name.siren24.com");

  

$1이  의미하는  바가  뭘까를  찾아보자

  

replaceAll을  api에서  살펴보면  다음과  같다.

  
replaceAll

public  String  replaceAll(String  regex,
                                                  String  replacement)

        Replaces  each  substring  of  this  string  that  matches  the  given  regular  expression  with  the  given  replacement.

        An  invocation  of  this  method  of  the  form  str.replaceAll(regex,  repl)  yields  exactly  the  same  result  as  the  expression

                Pattern.compile(regex).matcher(str).replaceAll(repl)

        Parameters:
                regex  -  the  regular  expression  to  which  this  string  is  to  be  matched  
        Returns:
                The  resulting  String  
        Throws:
                PatternSyntaxException  -  if  the  regular  expression's  syntax  is  invalid

주의해서  볼것은  str.replaceAll(regex,  repl)이  Pattern.compil(regex).matcher(str).replaceAll(repl)과  같다는  내용이다.

즉  replaceAll의  앞  인자는  regular  expression을  쓸  수  있고

  뒤  repl은  matcher의  replaceAll  인자와  같은  역할을  할  수  있다는  것이다.

  

아래는  matcher의  replaceAll
replaceAll

public  String  replaceAll(String  replacement)

        Replaces  every  subsequence  of  the  input  sequence  that  matches  the  pattern  with  the  given  replacement  string.

        This  method  first  resets  this  matcher.  It  then  scans  the  input  sequence  looking  for  matches  of  the  pattern.  Characters  that  are  not  part  of  any  match  are  appended  directly  to  the  result  string;  each  match  is  replaced  in  the  result  by  the  replacement  string.  The  replacement  string  may  contain  references  to  captured  subsequences  as  in  the  appendReplacement  method.

        Note  that  backslashes  (\)  and  dollar  signs  ($)  in  the  replacement  string  may  cause  the  results  to  be  different  than  if  it  were  being  treated  as  a  literal  replacement  string.  Dollar  signs  may  be  treated  as  references  to  captured  subsequences  as  described  above,  and  backslashes  are  used  to  escape  literal  characters  in  the  replacement  string.

        Given  the  regular  expression  a*b,  the  input  "aabfooaabfooabfoob",  and  the  replacement  string  "-",  an  invocation  of  this  method  on  a  matcher  for  that  expression  would  yield  the  string  "-foo-foo-foo-".

        Invoking  this  method  changes  this  matcher's  state.  If  the  matcher  is  to  be  used  in  further  matching  operations  then  it  should  first  be  reset.

        Parameters:
                replacement  -  The  replacement  string  
        Returns:
                The  string  constructed  by  replacing  each  matching  subsequence  by  the  replacement  string,  substituting  captured  subsequences  as  needed

즉  replacement에  "$1"과  같이  매치된  내용을  사용할  수  있다.

$1은  regexp에서  매치된  첫번째  결과물을  의미한다.

  

  

다시  예제  코드를  보면

referer  =  referer.replaceAll("(?i:https?://([^/]+)/.*)",  "$1");

assertEquals(referer,  "name.siren24.com");

  

(?i:https?://([^/]+)/.*)    의  의미를  하나  하나  분석해보자

  

regexp에서  그룹을  지을때  괄호를  사용하는데  두가지  그룹이  있다.  하나는  non-capturing  group이고  또  다른  하나는  capturing  group이다.

(?:  )  <--  non-capturing  group

  (  )  <--  captureing  group

  

non-capturing  group은  식을  묶어주거나  구분을  위해  사용하고  capturing  group은  같은  목적을  위해  사용하지만

매치되는  결과물들을  저장해서  나중에  쓸  수  있도록  한다는  점이  차이가  있다.

  

(?i:https?://([^/]+)/.*)

이건  non-capturing  group이다

?i:  <--  ??    i는  나중에  설명

  

(?i:https?://([^/]+)/.*)

이건  capturing  group

  

일단  여기까지  그다음

  

https?://([^/]+)/.*

첫째  s?는  s가  있을수도  있고  없을수도  있다는  말이다.

즉  http://  이런것도  매치가  되고  https://도  매치가  된다.

둘째  .은  모든  문자를  의미한다.  어떤문자든  한문자에  매치된다

그다음  *는  앞에게  지시하는  내용이  없을수도  있고  몇번이든  반복될  수  있다는  수량의  의미를  나타낸다.

그러면  .*는  없을수도  있고  내용이  무한이  길어질수도  있다라는  의미

예를  들면  a*  라고  하면

아무것도  없는것도  OK

a  도  OK

aa  도  OK

aaa    도  OK

  

https?://([^/]+)/.*)

[  ]안에는  character들이  들어갈  수  있다.

^는  [  ]  안에서  쓰이면  문자  ^가  아니라  여집합을  의미한다.

[^/]  라고  하면  /라는  문자를  제외한  모든  문자가  된다.

  +는  *와  같이  수량을  나타내는데  반드시  한번  이상은  반복된다는  의미이다.

그러니    [^/]+를  해석해보면  /가  아닌문자가  적어도  한자는  있다는  의미

(도메인정보에는  /가  포함될수  없으므로  위와  같은  방식을  사용한다.)

그런데  도메인  정보를  얻는  부분에  (  )  capturing  group을  설정했다.

즉  매치된  정보를  나중에  이용할  수  있다는  의미

  

아까  설명안한  i를  보자

(?i:https?://([^/]+)/.*)

Pattern  클래스를  이용할때는  여러  옵션을  설정할수  있는데

replaceAll을  쓰는  경우  이런  옵션들을  ?와  :  사이에  문자를  써서  정규표현식  모드를  지정할  수  있다.

예를  들면  i는  Pattern.CASE_INSENSITIVE와  같은  대소문자  구분을  하지  않는  모드를  설정한다

s  는  Pattern.DOTALL의  의미    이외에도  d,  m,  x,  u  등의  옵션이  있다.
  

이제  이  한줄을  다시  보면

referer  =  referer.replaceAll("(?i:https?://([^/]+)/.*)",  "$1");

정규식을  이용해서  원하는  부분을  설정하고  여기서는  url전체  그중에  캡쳐하고  싶은부분을  지정하고  (  도메인부분  )

그리고  변경될  내용에  캡쳐된  부분을  지정해서  바꾸게  했다.  $1은  첫번째  캡처링그룹의  결과물을  가르킨다  (  이  예에서는  도메인정보  )
  

String  referer  =  "http://name.siren24.com/servlet/name_check";

referer  =  referer.replaceAll("(?i:https?://([^/]+)/.*)",  "$1");      <--  도메인부분만  찾아서  전체스트링을  치환

assertEquals(referer,  "name.siren24.com");
  

다른  주의  사항들은  여기를  참고해  보자

http://mean79.tistory.com/60

[출처]  java  replaceAll  잘쓰기|작성자  단
http://blog.naver.com/zican?Redirect=Log&logNo=60048376969

1750 view

4.0 stars