Tips in Action‎ > ‎정규식‎ > ‎

루프내에서의 정규식 효율 높이기

전종필

정규식을 사용할 때, 임의의 내용을 적용할 경우가 종종 있습니다. 특히 이 정규식이 for, foreach, while 등의 루프 안에서 사용될 경우가 이 팁의 논의 대상입니다.
정규식 안에서 변수를 사용할 경우, 프로그램은 루프를 돌 때 마다 이 변수의 값을 질의하여 대치한 후 사용해야 합니다.

# 변수 $input을 정규식에 적용한다고 합시다.
while($line=<FILE>) {
	if( $line =~ /$input/ ) {
		push @found, $line;
	}
}
위와 같은 경우 $input은 while 루프내에서 한 번도 변하지 않을 것입니다. 그런데, 매번 $input의 값을 질의하여 사용한다면 손해라는 느낌이 들 것입니다.
이럴때 정규식에 /$input/o와 같이 o 옵션을 사용합니다.

while($line=<FILE>) {
	if( $line =~ /$input/o ) {
		push @found, $line;
	}
}
이와 같이 하면 Perl은 이 값을 루프의 처음 한 번만 질의하고, 그 다음에는 그 값을 계속해서 사용합니다. 하지만 $input의 값이 루프 내에서 한번이라도 변한다면 이 옵션을 사용하면 안되겠지요.
이 옵션은 s///에서도 마찬가지로 사용할 수 있습니다.

$keys = join( '|', @ARGV );
while($line=<FILE>) {
	if( $line =~ s/^($keys)=(.+)/$1="$2"/o ) {
		push @lines, $line;
	}
}
정말 그런지 의심스러우시다면 다음 코드를 직접 실행시켜 보시기 바랍니다.

@arr = qw( aaa bbb ccc );
@data = qw( aaa=1 xxx=4 bbb=55 ccc=87 rrr=87 );
my $keys = join( '|', @arr);
print "$keys\n";
foreach my $d ( @data ) {
        if( $d =~ s/^($keys)=(.+)/$1="$2"/o ) { # xxx=4 부터 $keys는 HELLO이지만 o 옵션때문에 괜찮습니다.
                push @lines, $d;
        }
        $keys = "HELLO"; # 여기 일부러 변화를 !!!
}
print "$keys\n";

print join("\n",@lines,'');
출력되는 내용은

aaa|bbb|ccc
HELLO
aaa="1"
bbb="55"
ccc="87"
입니다. 루프가 아닌 경우라도 같은 패턴을 여러번 사용한다면 역시 마찬가지로 적용할 수 있습니다.  
Comments