2012-03-12 5 views
0

커맨드 라인에서 인수를 취하여 스크립트 내의 정규식으로 사용하여 파일의 라인을 필터링하고 싶습니다. 간단한 예를 script.pl에서특정 값을 가진 라인을 필터링하기위한 커맨드 라인 인수로서의 정규식

$ perl script.pl id_4 

:

... 
my $exp = shift; 
while(my $line = <$fh){ 
    if($line =~ /$exp/){ 
     print $line,"\n"; 
    } 
} 
... 

내 실제 스크립트는 좀 더 복잡하고 정보를 추출하고 다른 출력을 생성하기 위해 라인에 다른 조작을 수행합니다. 내 문제는 내가 "id_4"를 포함하는 선만 선택하는 대신 "id_4"가 포함 된 모든 행을 걸러 내고 싶은 상황이 있다는 것입니다. 일반적으로이

if($line !~ /$exp/) 

에 의해 달성 될 수 있지만, 가능하면, 내가 인수의 더 복잡한 설정을 받아 내 스크립트를 변경하지 않으려는 (두 번째 매개 변수는 "NE"경우 예 : !~을 사용하고 =~ 경우 아니).

누구나 ("id_1 | id_2 | id_3 | id_5 ..."옆에있는) 여러 가지 가능성 중에서 하나의 특정 값을 포함하는 행을 필터링 할 수있는 정규식을 생각할 수 있습니까? 나는 여기에 도둑질을 요구하고 두려움에 빠지며 아마 단지 합리적인 것을 고수해야하고 또 다른 주장을 받아 들여야한다.

+2

, 당신이 최고의 옵션으로 제안한 "없습니다"(또는'그렙 용어로 -v') 인수를 추천 할 것입니다. 거짓 우아함을 위해 코드를 복잡하게 작성하지 마십시오. – DVK

답변

1

왜 선택합니까? 둘 다.

my $exp = join "|", grep !/^!/, @ARGV; 
my @not = grep /^!/, @ARGV; 
s/^!// for @not; 
my $exp_not = join "|", @not; 

... 
if (($line =~ $exp) && ($line !~ $exp_not)) { 
    # do stuff 
} 

사용법 : 솔직히

perl script.pl orange soda !light !diet 
+0

grep과 같은 기능이 perl에서 구현되었다는 사실조차 몰랐습니다. 놀랄 만한! – MattLBeck

+0

@kikumbob 필자는 [perldoc perlfunc] (http://perldoc.perl.org/perlfunc.html)를 추천 할 수 있습니다. :) – TLP

0

정규 표현식을 반전하는 방법이 있으므로 "subexpr과 일치하지 않는 모든 문자열"과 같은 일치 항목을 사용할 수 있습니다. 이를 직접 표현하는 연산자가 없으면 (즉, 기본 양성 일치 정규식 연산자 만 사용) 여전히 가능하지만 크고 다루기 힘든 정규 표현식 (정규 표현식 크기의 조합 폭발 일 가능성이 있음)이 발생합니다.

간단한 예를 들어,이 질문에 대한 내 대답을보십시오 : 문자열 "help"이외의 모든 것과 일치하는 정규식을 작성하는 방법. (이 경기는 시작과 끝을 고정하는 아주 단순화합니다.) 당신은 단지 전체 식의 경기를 반전 할 때 Match all letter/number combos but specific word?

전통적인 유닉스 도구는 상황에 대한 해킹이 있습니다 grep -vgrep. 또는 vi : :g/pat/:v/pat/ 등. 이런 식으로 구현자는 간단한 NFA 구축 방식에 맞지 않는 어려운 정규 표현식 연산자를 구현하지 못했습니다.

가장 쉬운 방법은 동일한 패턴을 사용하고 굵은 - 거친 부정에 대한 규칙 인 include 패턴과 exclude 패턴을 사용하는 것입니다.

+0

물론 Perl은 부정적인 lookahead 어서션 (예 :'/^(?!.* id_5) /')을 지원하기 때문에 이러한 종류의 복잡성은 실제로 필요하지 않습니다. :-) – ruakh

관련 문제