블록으로 구성된 파일에 집계된 데이터가 있습니다.
---- 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
대신 블록 내부에서 카운터 변수를 증가시키는 등 다른 방법을 사용할 수 있습니다.if
s///
---- BLOCK...
그런데 머리글 과 바닥글을 유지하려면 ------*
및 줄을 로 바꾸고 테스트를 로 변경하세요.shift
pop
$file = $F[0]
if
if (@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 = ())
.
그렇지 않으면 섹션을 시작 (/^-/)
하고 현재 행을 배열의 첫 번째 값으로 저장한 다음 제목이 됩니다.
빈 줄을 제거했지만 원하시면 그대로 두셔도 됩니다.