2013-03-31 2 views
3

그래서 명령 행에서 각 로그 행의 \ n을 제거하지 않고 로그 행에서 임베디드 된 \ n을 제거하려고합니다. 나는 이것들을 시험해 보았다. 그리고 그들은 모두 all \ n을 ~로 바꾸었다.펄 정규식 스크립트 및 명령 줄이 다릅니다

cat test1.txt | perl -n -e 's{\n(?!2013)}{~}mg;print' > test1a.fix 
    perl -n -e 's{\n(?!2013)}{~}mg;print' test1.txt > test1b.fix 

모두 부정적인 시각을 무시합니다.

있는 test1.txt는

2013-03-01 12:23:59,1 
    line2 
     line3 
    2013-03-01 12:23:59,4 

test1a.fix를 포함하고 test1b.fix는

2013-03-01 12:23:59,1~line2~ line3~2013-03-01 12:23:59,4 

을 포함하지만이 스크립트를 사용하여 정규식 함께했다.

#!/usr/bin/perl 
    use warnings; 
    use strict; 

    sub test { 
     my ($str, $expect) = @_; 
     my $mod = $str; 
     $mod =~ s{\n(?!2013)}{~}mg; 
     print "Expecting '$expect' got '$mod' - "; 
     print $mod eq $expect ? "passed\n" : "failed\n"; 
    } 

    test("2013-03-01 12:23:59,line1 
    line2 
     line3 
    2013-03-01 12:23:59,line4", "2013-03-01 12:23:59,line1~line2~ line3 
    2013-03-01 12:23:59,line4"); 

그리고 내가 원하는 것과 일치하는 다음 출력을 생성합니다.

[email protected]:~/logs> ./regex_test.pl 
    Expecting '2013-03-01 12:23:59,line1~line2~ line3 
    2013-03-01 12:23:59,line4' got '2013-03-01 12:23:59,line1~line2~ line3 
    2013-03-01 12:23:59,line4' - passed 
    [email protected]:~/logs> 

다른 사람들이 왜 다르게 작동하는지 그리고 어떻게 명령 줄에서이 작업을 수행 할 수 있는지 설명 할 수 있습니까?

답변

4

perl -n은 한 번에 한 줄씩 파일을 처리합니다. 행을 읽을 때, 줄 바꿈은 문자열의 끝에 있고 정규식이 예상하는 시작은 아닙니다. \n이 아닌 행의 시작과 일치 시키려면 ^을 사용해야합니다.

함수 버전에서는 전체 줄을 한꺼번에 처리합니다. 이 경우 줄 바꿈은 문자열의 중간에 있고 정규 표현식과 일치합니다.

2

명령 줄 프로그램은 한 번에 하나의 "입력 레코드"(a.k.a.line) 만 볼 수 있습니다. 필자는 입력 레코드 분리 자 $ /를 스톰핑하여 예제를 만들 수있었습니다.

perl -n -e '$/=undef; s{\n(?!2013)}{~}mg;print' test1.txt > test1c.fix 

이렇게하면 각 "줄"이 전체 입력으로 재정의되고 실제로 스크립트와 비슷하게 작동합니다.

cat test1c.fix 
2013-03-01 12:23:59,1~line2~ line3 
2013-03-01 12:23:59,4~ 
+1

감사합니다. 명령 줄 perl에 대한 여러 줄 옵션을 검색하여 -0777 플래그가 발견되어 올바르게 작동합니다. perl -0777 -n -e '{\ n (?! 2013)} {~} mg; print'test1.txt> test1c.fix 모두 감사합니다. –

+0

여기에서 뭔가를 배웠습니다. (perl --help : -0 [8 진수로 레코드 분리 자 지정] – ddoxey