Linux, UNIX 및 Windows용 DB2 9.7과 정규식
프로그래밍에서 정규식은 regex 또는 regexp로도
알려진 형식 언어로 작성된다. 특정 프로그램이 패턴 일치라는 인식 프로세스를
사용하여 문자열 또는 텍스트에서 검색하는 형식 패턴이 정규식이다.
패턴 일치 및 정규식을 사용하여 다음과 같은 기본 함수를 수행하려고 할 수 있다.
- 지정된 시퀀스가 지정된 패턴과 비슷한지 확인하기
- 시퀀스에 특정 패턴이 있는 경우 서브시퀀스를 대체 서브시퀀스로 대체하기
- 지정된 입력 시퀀스에서 특정 서브시퀀스의 발생 일치시키기
- 지정된 입력 시퀀스에서 서브시퀀스의 특정 발생 및 위치 일치시키기
Linux, UNIX 및 Windows용 DB2는 기본적으로 정규식 함수 사용을 지원하지 않는다. 정규식 함수를 사용해야 하는 인스턴스가 발생하면 사용자 정의 함수를 작성하여 요구사항을 처리해야 할 것이다.
이 기사에서는 사용자의 고유 Java 사용자 정의 함수를 작성하여 패턴 일치에
대한 원자적 기능을 제공하는 java.util.regex
패키지의 혜택을 받는 방법을 보여 준다. 이 패키지는 정규식의 컴파일된
표현식인 패턴을 해석하여 문자 시퀀스에 대한 조작을 수행하는 엔진을 제공한다.
Java 패턴은 Unicode Technical Standard #18: Unicode Regular Expression
지침의 Level 1과 RL2.1 Canonical Equivalents를 준수한다.
이 기사에서 다루는 솔루션에서는 조합 순서, 확장 문자소 클러스터 또는 조정된 문자소 클러스터에 대한 지원은 제공하지 않는다.
이 기사에는 다음과 같은 섹션이 포함되어 있다.
- Java
regex함수 - Java 함수에 대한 스펙을 제안한다. - 일치 모드 - 함수의
MODE매개변수를 통해 지정할 수 있는 다양한 유형의 패턴 일치에 대해 설명한다. - 예제 Java 코드 -
regex함수를 구현하는 데 사용할 수 있는 Java 코드와 DB2 사용자 정의 함수에 대한 관련 코드의 예제를 보여 준다. - 인에이블먼트 - 재사용할 수 있는 완전한 예제를 제공하는 이 기사에서 다운로드 가능한 zip 파일을 처리하는 방법에 대해 설명한다.
- 예제 SQL문 - 이 기사에서 다루는 DB2 Java 사용자 정의 함수를 사용하여 일부 SQL 쿼리를 공식화한다.
INTEGER REGEXP_LIKE (SOURCE VARCHAR(3000),
REGEX VARCHAR(512),
MODE VARCHAR(3) )
|
이 함수는 지정된 정규식을 지정된 모드를 가진 패턴으로 컴파일하고 지정된 입력을 이에 대해 일치시킨다.
매개변수:
- source: 정규식이 일치되는 입력 문자열이다.
- regex: 정규식이다.
- mode: 일치 모드이다.
- CASE_INSENSITVE_MODE
- DOTALL_MODE
- MULTI_LINE_MODE
리턴값:
- 소스가 정규식에 대해 일치되는 경우에는
True값이 리턴되고 그렇지 않으면false값이 리턴된다. - 지정된 모드는 올바른 모드여야 한다. 그렇지 않으면
false가 리턴된다. - 정규식의 형식이 올바르지 않으면
false가 리턴된다. - 소스 문자열이 널(null)이거나 비어 있는 경우에는
0이 리턴된다.
VARCHAR(3000) REGEXP_REPLACE (SOURCE VARCHAR(3000), REGEX VARCHAR(512), REPLACEMENT VARCHAR(3000), POSITION INTEGER, OCCURRENCE INTEGER, MODES VARCHAR(3)) |
이 함수는 문자열에서 지정된 패턴을 검색하여 새로운 값으로 대체한다.
매개변수:
source: 검색이 수행되는 문자열이다.pattern: 검색할 패턴이다.Replacement: 찾은 문자열을 대체할 문자열이다.
대체 문자열에는 이전의 일치 중에 캡처된 서브시퀀스에 대한 참조가 포함될 수 있다.
각각의
$g발생은 그룹 평가의 결과(g)로 대체된다.$뒤에 처음으로 오는 숫자는 언제나 그룹 참조의 일부로 처리된다. 그 뒤의 숫자들은 올바른 그룹 참조를 형성하는 경우g에 통합된다.0에서9까지의 숫자만 그룹 참조의 잠재적 컴포넌트로 간주된다. 예를 들어, 두 번째 그룹이 문자열foo와 일치한 경우 대체 문자열$2bar를 전달하면foobar가 문자열 버퍼에 추가된다.달러 표시(
$)는 앞에 백슬래시를 추가하여(\$) 대체 문자열에 리터럴로 포함될 수 있다.startPosition: 검색 문자열에서 검색을 시작하려고 하는 위치이다. 이 값은1이상이어야 한다.1보다 작은 값을 사용하면 이 메소드가 널(null)을 리턴한다. 첫 번째 문자의 위치는1이다.occurrence: 발생 매개변수는 대체할 일치를 지정한다.0값은 모든 값을 대체한다는 것을 의미한다. 지정된 숫자가 0보다 큰 경우에는 찾은 발생만 대체된다. 필요한 것보다 적은 수의 일치를 찾은 경우에는 소스에 대해 아무 작업도 수행되지 않는다.mode: 일치 모드이다.
리턴값:
대체 값으로 대체된 적절한 정규식 일치가 포함된 문자열이다. 소스 문자열이 널(null)이거나 비어 있는 경우에는 널(null)을 리턴한다.
VARCHAR(3000) REGEXP_SUBSTR ( SOURCE VARCHAR(3000), REGEX VARCHAR(512), POSITION INTEGER, OCCURRENCE INTEGER, MODES VARCHAR(3) ) |
이 함수는 소스 문자열에 대해 정규식에 의해 정의되는 패턴의 특정 발생을 일치시키고 리턴한다.
매개변수:
source: 검색이 수행되는 문자열이다.pattern: 검색할 패턴이다.startPosition: 검색 문자열에서 검색을 시작하려고 하는 위치이다. 이 값은1이상이어야 한다.1보다 작은 값을 사용하면 이 메소드가 널(null)을 리턴한다. 첫 번째 문자의 위치는1이다.occurrence: 발생 매개변수는 값을 가져올 일치를 지정한다.1값은 첫 번째 일치를 가져오는 것을 의미하고 더 큰 숫자는 지정된 모든 일치를 찾을 때까지 이전 일치의 끝에서 시작한regex에 대한 일치 시도가 수행되며 마지막 일치만 리턴된다는 것을 의미한다. 필요한 것보다 적은 수의 일치를 찾은 경우에는 널(null)이 리턴된다.mode: 일치 모드이다.
리턴값:
이전 일치의 서브시퀀스를 리턴한다. 일치를 찾지 못하거나 소스 문자열이
널(null)이거나 비어 있는 경우에는 널(null)을 리턴한다. 위치 0은
소스 문자열의 첫 번째 문자이다.
INTEGER REGEXP_INSTR ( SOURCE VARCHAR(3000), REGEX VARCHAR(512), POSITION INTEGER, OCCURRENCE INTEGER, ROPT INTEGER, MODES VARCHAR(3)) |
이 함수는 소스 문자열에 대해 정규식에 의해 정의되는 패턴의 특정 발생을 일치시킨다. 그런 다음 일치된 발생의 첫 번째 문자 또는 일치된 발생 뒤의 첫 번째 문자의 소스 문자열에서의 위치를 리턴한다.
매개변수:
source: 검색이 수행되는 문자열이다.pattern: 검색할 패턴이다.startPosition: 검색 문자열에서 검색을 시작하려고 하는 위치이다. 이 값은1이상이어야 한다.1보다 작은 값을 사용하면 이 메소드가0을 리턴한다. 첫 번째 문자의 위치는1이다.occurrence: 발생 매개변수는 가져올 일치를 지정한다.1값은 첫 번째 일치를 가져온다는 것을 의미한다. 더 큰 숫자는 지정된 모든 일치를 찾을 때까지 이전 일치의 끝에서 시작한regex에 대한 일치 시도가 수행된다는 것을 의미한다. 마지막 일치만 리턴된다. 필요한 것보다 적은 수의 일치를 찾은 경우에는0이 리턴된다.returnOption: returnOption을0으로 설정하여 일치의 첫 번째 문자 위치를 가져온다.1로 설정된 경우에는 일치 뒤의 첫 번째 문자 위치가 리턴된다. 다른 값으로 설정하면 패턴을 찾을 수 없게 되어0이 리턴된다.Mode: 일치 모드이다.
리턴값:
이 값은 문자 일치 위치이다. 위치 1은 소스 문자열의
첫 번째 문자이다. 일치를 찾을 수 없는 경우에는 0이
리턴되고 소스 문자열이 널(null)이거나 비어 있는 경우에는 -1이
리턴된다.
네 개의 regex 함수 각각이 승인하는 모드 매개변수는
네 가지 가능한 모드 중 최대 세 개의 문자로 된 문자열이어야 한다.
i 모드는 대소문자를 구분하지 않는 일치를 설정하고
inm은 세 가지 해당 옵션을 설정한다.
i 모드와 c 모드는 상호 배타적이다.
이 매개변수를 생략하거나 비어 있는 문자열을 전달하면 기본 일치 모드가 사용된다.
i모드: 대소문자를 구분하지 않는 일치를 설정한다. 기본값은 대소문자를 구분하는 것이다.c모드: 대소문자 구분 일치를 설정한다.n모드: 마침표(.)가 모든 문자(줄 바꾸기 포함)와 일치하도록 만든다. 기본적으로 마침표(.)는 줄 바꾸기를 제외한 모든 문자와 일치한다.m모드: 캐럿 기호(^)와 달러 표시($)가 각 행의 시작과 끝에서 일치하도록 만든다(예: 소스 문자열에 포함된 줄 바꿈 앞과 뒤). 기본적으로 이들은 문자열의 맨 앞과 맨 뒤에서만 일치한다.
위 모드 중 어느 것도 지정되지 않은 경우 리턴되는 값은 UNIX_LINES이며
이는 ., ^ 및 $의
동작에서 \n 행 종결자만 인식된다는 것을 의미한다.
위에서 설명한 지정된 매개변수를 사용하여 지정된 모드는 다음 패턴을
존중해야 한다.
^([nmi]{0,3})|([nmc]{0,3})$.
지정된 모드가 올바르지 않은 경우에는 regex 함수 중
어느 함수라도 오류를 리턴한다.
Regexp Java 클래스
package com.ibm.avalanche.udf.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class Regexp
{
private static final String CASE_INSENSITVE_MODE = "i";
private static final String CASE_SENSITVE_MODE = "c";
private static final String DOTALL_MODE = "n";
private static final String MULTI_LINE_MODE = "m";
public static int regexpInstr(String source, String pattern, int startPosition,
int occurrence, int returnOption, String mode) {...}
public static String regexpSubstr(String source, String pattern, int startPosition,
int occurrence, String mode) {...}
public static String regexpReplace(String source, String pattern, String replacement,
int startPosition, int occurrence, String mode) {...}
public static int regexpLike(String source, String regex, String mode) {...}
public static int setMode(String mode) {…}
}
|
regexpLike 함수
public static int regexpLike(String source, String regex, String mode)
{
int flags = 0;
if ( source == null || source.length()<1)
{
return 0;
}
if ((flags = setMode(mode)) == -1)
{
return 0;
}
try
{
Matcher matcher = Pattern.compile(regex, flags).matcher(source);
if (matcher.find())
{
return 1;
}
}
catch (PatternSyntaxException e)
{
return 0;
}
return 0;
}
|
regexpReplace 함수
public static String regexpReplace(String source, String pattern, String replacement,
int startPosition, int occurrence, String mode)
{
int flags = -1;
if ( source == null || source.length()<1)
{
return null;
}
if ((replacement == null) || (startPosition-- <= 0) || ((flags = setMode(mode)) == -1))
{
return source;
}
Pattern pat;
try
{
pat = Pattern.compile(pattern, flags);
}
catch (PatternSyntaxException e)
{
return source;
}
Matcher matcher = pat.matcher(source);
int count = 0;
StringBuffer sb = new StringBuffer();
if (matcher.find(startPosition))
{
if (occurrence == 0)
{
matcher.appendReplacement(sb, replacement);
while (matcher.find())
{
matcher.appendReplacement(sb, replacement);
}
}
else
{
do
{
if (++count == occurrence)
{
matcher.appendReplacement(sb, replacement);
break;
}
} while (matcher.find());
}
matcher.appendTail(sb);
return sb.toString();
}
return source;
}
|
regexpSubstr 함수
public static String regexpSubstr(String source, String pattern, int startPosition,
int occurrence, String mode)
{
int flags = -1;
if ( source == null || source.length()<1)
{
return null;
}
if ((startPosition-- <= 0) || ((flags = setMode(mode)) == -1))
{
return null;
}
Pattern pat;
try
{
pat = Pattern.compile(pattern, flags);
}
catch (PatternSyntaxException e)
{
return null;
}
Matcher matcher = pat.matcher(source);
String out = null;
int count = 0;
if (matcher.find(startPosition))
{
out = matcher.group();
count++;
while ((count < occurrence) && (matcher.find()))
{
out = matcher.group();
count++;
}
}
return (out = (count != occurrence) ? null : out);
}
|
regexpInstr 함수
public static int regexpInstr(String source, String pattern, int startPosition,
int occurrence, int returnOption, String mode)
{
int flags = -1;
if ( source == null || source.length()<1)
{
return -1;
}
if ((returnOption != 1) && (returnOption != 0) || (startPosition-- <= 0) ||
((flags = setMode(mode)) == -1))
{
return 0;
}
Pattern pat;
try
{
pat = Pattern.compile(pattern, flags);
}
catch (PatternSyntaxException e)
{
return 0;
}
Matcher matcher = pat.matcher(source);
int out = 0;
int count = 0;
if (matcher.find(startPosition))
{
out = (returnOption == 0 ? matcher.start() : matcher.end()) + 1;
count++;
while ((count < occurrence) && (matcher.find()))
{
out = (returnOption == 0 ? matcher.start() : matcher.end()) + 1;
count++;
}
}
return (out = (count != occurrence) ? 0 : out);
}
|
setModes 함수
public static int setMode(String mode)
{
int flag = Pattern.UNIX_LINES;
try
{
if (!Pattern.matches("^([nmi]{0,3})|([nmc]{0,3})$", mode))
{
return -1;
}
flag |= (mode.contains(CASE_INSENSITVE_MODE) ? Pattern.CASE_INSENSITIVE : 0);
flag |= (mode.contains(DOTALL_MODE) ? Pattern.DOTALL : 0);
flag |= (mode.contains(MULTI_LINE_MODE) ? Pattern.MULTILINE : 0);
// Meaningless from the code point of view but is made to insure consistency with
Oracle modes. This // method has to provide the CASE_SENSITIVE_MODE mode for the
'c' option.
flag |= (mode.contains(CASE_SENSITVE_MODE) ? 0 : 0);
}
catch (PatternSyntaxException e)
{
return -1;
}
catch (NullPointerException ne)
{
return -1;
}
return flag;
}
|
DB2에서 JAR 파일 전개하기
CALL SQLJ.INSTALL_JAR('file:C:\avalanche\db2_regex\lib\db2_regex.jar', db2_regex);
@
|
사용자 정의 함수 REGEXP_LIKE
CREATE OR REPLACE FUNCTION REGEXP_LIKE(SOURCE VARCHAR(3000), REGEX VARCHAR(512), MODE VARCHAR(3)) RETURNS INTEGER FENCED NOT DETERMINISTIC NO SQL LANGUAGE JAVA PARAMETER STYLE JAVA EXTERNAL NAME 'db2_regex:com.ibm.avalanche.udf.regex.Regexp.regexpLike' NO EXTERNAL ACTION @ |
사용자 정의 함수 REGEXP_REPLACE
CREATE OR REPLACE FUNCTION REGEXP_REPLACE(SOURCE VARCHAR(3000), REGEX VARCHAR(512), REPLACEMENT VARCHAR(3000), POSITION INTEGER, OCCURRENCE INTEGER, MODES VARCHAR(3)) RETURNS VARCHAR(3000) FENCED NOT DETERMINISTIC NO SQL LANGUAGE JAVA PARAMETER STYLE JAVA EXTERNAL NAME 'db2_regex:com.ibm.avalanche.udf.regex.Regexp!regexpReplace' NO EXTERNAL ACTION @ |
사용자 정의 함수 REGEXP_SUBSTR
CREATE OR REPLACE FUNCTION REGEXP_SUBSTR(SOURCE VARCHAR(3000), REGEX VARCHAR(512), POSITION INTEGER, OCCURRENCE INTEGER, MODES VARCHAR(3)) RETURNS VARCHAR(3000) FENCED NOT DETERMINISTIC NO SQL LANGUAGE JAVA PARAMETER STYLE JAVA EXTERNAL NAME 'db2_regex:com.ibm.avalanche.udf.regex.Regexp!regexpSubstr' NO EXTERNAL ACTION @ |
사용자 정의 함수 REGEXP_INSTR
CREATE OR REPLACE FUNCTION REGEXP_INSTR(SOURCE VARCHAR(3000), REGEX VARCHAR(512), POSITION INTEGER, OCCURRENCE INTEGER, ROPT INTEGER, MODES VARCHAR(3)) RETURNS INTEGER FENCED NOT DETERMINISTIC NO SQL LANGUAGE JAVA PARAMETER STYLE JAVA EXTERNAL NAME 'db2_regex:com.ibm.avalanche.udf.regex.Regexp!regexpInstr' NO EXTERNAL ACTION @ |
다음 단계에서는 샘플 코드를 다운로드하여 사용하는 방법에 대해 보여 준다.
- 첨부된
db2-regex.zip파일을 하드 디스크의 새 폴더(예:C:\avalanche)에 저장한다. - Zip 파일의 모든 파일을
C:\avalanche\db2_regex에 압축 해제한다. C:\avalanche\db2_regex\scripts\sql\db2_regex_functions.sql을 연다.- 환경에 맞게 스크립트를 편집한다. 두 번째 행에서 디렉토리 이름을 변경한다.
UNIX를 사용하는 경우에는 구문이 다음과 비슷하다.
CALL SQLJ.INSTALL_JAR('file:/tmp/avalanche/db2_regex/lib/db2_regex.jar', db2_regex)
- DB2 명령행 프로세서 창에서 다음 명령행을 실행한다.
db2 connect to <my_db> user <uid> using <pwd> db2 set current schema='REGEXP' db2 -td@ -vf "C:\avalanche\db2_regex\scripts\sql\db2_regex_functions.sql"
패키지를 이미 전개했을 때 해당 패키지를 다시 전개하려는 경우(예: Java 코드를 이미 수정했을 때 업데이트된 코드를 사용하려는 경우) 다음 단계를 수행한다.
- Zip 파일을
C:\avalanche\db2_regex에 압축 해제한다. - DB2 명령 창에서 다음 명령을 실행한다.
db2 connect to <my_db> user <uid> using <pwd> db2 set current schema='REGEXP' db2 drop function REGEXP_LIKE db2 drop function REGEXP_REPLACE db2 drop function REGEXP_SUBSTR db2 drop function REGEXP_INSTR db2 call SQLJ.REMOVE_JAR(db2_regex) db2stop force db2start db2 connect to <my_db> user <uid> using <pwd> db2 set current schema='REGEXP' db2 -td@ -f C:\avalanche\db2_regex\scripts\sql\db2_regex_functions.sql
어느 지점에서도 오류가 발생하지 않았다는 것을 확인해야 한다.
select ID from REGEXP.REGEXP_STRINGS where REGEXP_LIKE(STRING, '^.EF[ ]+SAVEALIAS[ ]+[0-9]+', 'c') > 0 select ID from REGEXP.REGEXP_STRINGS where REGEXP_REPLACE(STRING, '^.EF[]+SAVEALIAS[ ]+[0-9]+', 'XX', 1, 1, 'c')='XX' select ID from REGEXP.REGEXP_STRINGS where REGEXP_SUBSTR(STRING, '^.EF[ ]+SAVEALIAS[ ]+[0-9]+', 1, 1, 'c')='DEF SAVEALIAS 2210' select ID from REGEXP.REGEXP_STRINGS where REGEXP_INSTR(STRING, '^.EF[ ]+SAVEALIAS[ ]+[0-9]+',1, 1, 1, 'c') > 0 |
이 기사에서는 DB2 Java 사용자 정의 함수를 작성하여 SQL문에서 정규식 함수를 처리하는 방법에 대해 살펴봤다.
네 가지 함수 예제에 대해 살펴봤으며 이러한 함수에 대해 새로운 함수를 확장, 수정 및 추가하여 사용자의 고유 요구사항과 더 잘 일치하게 할 수 있다.
또한 사용 가능한 다운로드를 사용하여 샘플이자 그대로 사용할 수 있는 코드의 전체 예제를 얻을 수 있다. 이러한 예제를 자유롭게 사용하고 수정하고 개인 용도에 맞게 조정할 수 있지만 활성 시스템에서 사용하기 전에 테스트하고 유효성을 검증해야 한다.
| 설명 | 이름 | 크기 | 다운로드 방식 |
|---|---|---|---|
| Sample files for this article | db2-regex.zip | 29KB | HTTP |
- 포럼에 참여하기.
- 기술 스펙에 대한 자세한 정보는 유니코드
기술 표준 웹 사이트에서 Unicode Regular
Expressions 항목을 참조하자.
- developerWorks의 DB2 for Linux, UNIX, and Windows 영역에서 DB2 기술을 향상시키는 데 도움이 되는 참고자료를 얻을 수 있다.
- Linux, UNIX 및 Windows용 DB2의
평가판을 다운로드할 수 있다.
Alexandre is a DB2 Migration Specialist in IBM's Project Avalanche. Alexandre worked as a real-time system engineer and software engineer consultant with industry majors in Europe before joining IBM as a developer in database cache technologies, where he contributed greatly in the advent of the first IBM solidDB Universal Cache generation.