텍스트 블록 추출 및 비교

텍스트 블록 추출 및 비교

블록으로 구성된 파일에 집계된 데이터가 있습니다.

---- BLOCK ONE ----
some data
another data
more data
more data
-------------------

---- BLOCK two ----
some data
another data
-------------------

---- BLOCK THREE ----
some data
another data
more data
-------------------

등. 총 블록 수는 약 2000개입니다.

항목(데이터 행)이 4개 미만인 블록을 추출해야 합니다. 이를 수행하는 방법을 알아두십시오(펄이 선호됩니다;)

답변1

$ perl -00 -F'\n' -n -e '
  $file = shift @F;
  pop @F;
  if (@F < 4) {
    $file =~ s/^---- | ----//g;
    open(OUT, ">", $file.".txt");
    print OUT join("\n", @F), "\n"
  }' input.txt

-00이 perl 한 줄 문은 단락 모드에서 입력을 읽고(두 개 이상의 줄 바꿈으로 구분됨) -F자동으로 줄 바꿈의 입력을 @F 배열로 분할하고 -n입력을 인쇄하지 않고 자동으로 읽는 데 사용됩니다 ( 와 유사 sed -n).

먼저 Shift를 사용하여 @F의 첫 번째 요소를 $file 변수에 넣습니다. 그런 다음 pop @F는 마지막 요소( -------------------)를 삭제합니다. 남은 요소가 4개 미만인 경우 $file에서 합계를 ----제거하고 ----쓰기를 위해 "$file.txt"를 연 다음 배열의 나머지 부분을 해당 파일에 인쇄합니다.

이러한 파일 이름이 마음에 들지 않으면 연산자를 사용하는 $file = sprintf "file%04i.txt", ++$counter대신 블록 내부에서 카운터 변수를 증가시키는 등 다른 방법을 사용할 수 있습니다.ifs///

---- BLOCK...그런데 머리글 과 바닥글을 유지하려면 ------*및 줄을 로 바꾸고 테스트를 로 변경하세요.shiftpop$file = $F[0]ifif (@F < 6)

출력 예( tail파일 이름 인쇄용):

$ tail BLOCK*.txt
==> BLOCK THREE.txt <==
some data
another data
more data

==> BLOCK two.txt <==
some data
another data

독립형 스크립트와 동일하지만 카운터를 사용하여 파일 이름을 생성합니다.

$ cat split-blocks.pl
#!/usr/bin/perl

use strict;
my $counter;

$/='';

while(<<>>) {
  my @lines = split /\n/;
  my $file = shift @lines;
  pop @lines;

  if (@lines < 4) {
    $file = sprintf 'file%04i.txt', ++$counter
    open(OUT, ">", $file) || die "couldn't open $file for write: $!\n";
    print OUT join("\n", @lines), "\n"
  }
};

$ ./split-blocks.pl input.txt

$ tail file*
==> file0001.txt <==
some data
another data

==> file0002.txt <==
some data
another data
more data

답변2

이것은 간단한 한 줄입니다.

$ perl -00 -lne '@k=(/\n/mg); print if $#k < 4 ' file
---- BLOCK two ----
some data
another data
-------------------

---- BLOCK THREE ----
some data
another data
more data
-------------------

-00빈 줄로 구분된 각 줄 블록을 단일 "줄"로 처리하는 단락 모드를 켭니다 . 각 호출에 -l줄 바꿈을 추가 하고 각 입력 "줄"에서 후행 줄 바꿈을 제거합니다. 즉, print각 입력 줄에서 " -n다음에 의해 제공된 스크립트를 실행합니다"를 의미합니다.-e

스크립트 자체는 \n입력 "라인"(문단)에서 문자를 찾아 배열에 저장합니다. 그런 다음 배열의 최대 인덱스가 4보다 작으면 해당 줄을 인쇄합니다. 배열은 처음부터 계산된다는 것을 기억하세요. 0이는 첫 번째 행도 계산되기 때문에 행이 4개 미만인 경우를 의미하지만 마지막 행은 후행 개행 문자가 제거되지 않았기 -l때문에 배열의 행 수가 4개 미만이고 차단되었습니다.

답변3

다음 중 하나를 사용하십시오 awk.

awk 'NF && !/^-/{ buf= buf (data?ORS:"") $0; data++ }
          /^-+$/{ if(data<4) { print (ors?ORS:"") buf; ors=ORS }; buf=data="" }' infile

산출:

some data
another data

some data
another data
more data

블록 머리글/바닥글을 유지하려면:

awk 'NF{ buf= buf (data?ORS:"") $0; data++ }
 /^-+$/{ if(data<=5) { print (ors?ORS:"") buf; ors=ORS }; buf=data="" }' infile

산출:

---- BLOCK two ----
some data
another data
-------------------

---- BLOCK THREE ----
some data
another data
more data
-------------------

답변4

perl -lne '
    if (/^-+$/) {
        print join "\n", @M, $_ if $#M < 4;
        @M = ();
        next;
    }

    if (/^-/) {
        $M[0] = $_;
        next;
    }

    push @M, $_ if $#M >= 0;
' file

자동 인쇄 옵션이 비활성화되어 있으므로 perl파일은 한 줄씩 읽혀집니다.perl(-n)

그런 다음 섹션 내부에 있으면 (push @M, $_ if $#M >= 0)해당 줄을 배열에 밀어 넣습니다.

끝 섹션 내부에 있고 (/^-+$/)배열 길이가 4보다 작으면 인쇄하고 배열을 지웁니다 (@M = ()).

그렇지 않으면 섹션을 시작 (/^-/)하고 현재 행을 배열의 첫 번째 값으로 저장한 다음 제목이 됩니다.


빈 줄을 제거했지만 원하시면 그대로 두셔도 됩니다.

관련 정보