파일에서 중복된 헤더/트레일러를 제거하는 Perl 스크립트

파일에서 중복된 헤더/트레일러를 제거하는 Perl 스크립트

10개의 파일을 하나로 병합하는 Perl 스크립트를 만들었습니다. 각 파일에는 파일에 키워드 제목/예고편이 있습니다. 따라서 병합된 파일에는 여러 개의 헤더 및 트레일러 키워드가 있습니다. 하지만 제목과 예고편은 병합된 파일의 시작과 끝에만 나타나도록 요구합니다.

예:

파일 1.txt -->

Header
Content1
Trailer

파일 2.txt -->

Header
Content2
Trailer

Merged.txt(현재) -->

Header
Content1
Trailer
Header
Content2
Trailer

Merged.txt(필수) -->

Header
Content1
Content2
Trailer

답변1

나는 그것을 할 것이다:

perl -i -lne 'print unless ($_ eq "Header" && $. > 1) || ($_ eq "Trailer" && !eof)' your-file

이 작업은 다음을 통해 수행할 수도 있습니다 sed.

sed -e 1b -e '$b' -e '/^Header$/d' -e '/^Trailer$/d' your-file

일부 sed구현에서는 Perl 스타일의 내부 편집이 가능하고, 일부(대부분)는 이를 사용하고 -i, 일부(FreeBSD 및 macos를 포함한 파생 제품)는 사용합니다.-i ''

병합할 때 추가 헤더/트레일러를 제거할 수 있습니다.

perl -lne '
  if (eof) {
    $n++;  # counts files
    close ARGV; # resets $.
    next if @ARGV; # if there are more files to process
  }
  print unless $. == 1 && $n # first list and not first file
  ' file<->.txt(n)

( file<->.txt(n)숫자로 file<number>.txt정렬을 일치시키려면 n(따라서 file10.txt및 사이에서 정렬하려면) , 사이 file9.txtfile11.txt에서 정렬하지 않으려면 쉘이 필요합니다 )file1.txtfile2.txtzsh

또는 GNU를 사용하여 sed(여전히 zsh):

() {
  head -n1 < $1
  sed -s -- '1d;$d' "$@"
  tail -n1 < $argv[-1]
} file<->.txt(n)

답변2

다음과 같이 시도해 보세요.

perl -ne 'if ($. == 1 || eof) { print ; next };
          print unless /Header|Trailer/' merged.txt

내용에 관계없이 첫 번째 줄과 마지막 줄은 물론 헤더나 트레일러가 포함되지 않은 모든 줄을 인쇄해야 합니다.

표준 출력으로 인쇄하는 대신 입력 파일을 수정하려면 Perl의 -i옵션을 사용하십시오. (하지만 출력이 원하는 것인지 확인할 때까지 이 작업을 수행하지 않는 것이 좋습니다. 예를 들어 다른 파일로 리디렉션하고 diff비교를 사용하십시오. 원본 텍스트와 함께).


약간만 수정하면 입력 파일 수를 연결하고 "헤더" 또는 "트레일러" 줄을 제거하는 동시에 첫 번째 파일의 첫 번째 줄과 마지막 파일의 마지막 줄이 항상 일치하도록 보장하는 데 사용할 수도 있습니다. 인쇄됩니다("제목" 또는 "예고편"이 포함된 경우에도). 예를 들어:

$ perl -ne 'if ($. == 1 || (! @ARGV && eof)) { print ; next };
            print unless /Header|Trailer/' file1.txt file2.txt 
Header
Content1
Content2
Trailer

첫 번째 문은 두 가지 조건을 테스트합니다.

  1. $. == 1현재 라인이 첫 번째 입력 라인인지 테스트합니다.

  2. (! @ARGV && eof)현재 줄이 마지막 파일의 마지막 줄인지 테스트합니다.

    스칼라 컨텍스트에서 평가하면 @ARGV명령줄 인수(파일 이름) 배열의 요소 수가 반환되고, 각 파일 이름은 shift처리를 위해 열릴 때 배열에서 제거되어 개수가 줄어듭니다. 마지막 파일의 결과는 0(false)이 됩니다. !마지막 파일을 읽을 때 이를 부정하면 ,

    AND 연산 eof(현재 파일의 끝이면 true)은 마지막 파일의 마지막 행에서만 true입니다.

조건 중 하나가 true이면 현재 행을 인쇄합니다.

두 번째 문은 "Header" 또는 "Trailer"와 일치하지 않는 한 현재 줄을 인쇄합니다.

그런데, unlessPerl 구문은 ("if not")과 동일합니다 if !. 때로는 "X가 아니면 Y를 수행합니다"라고 말하는 것이 더 자연스러우며, "X가 아니면 Y를 수행합니다"라고 말하는 것이 더 자연스럽습니다. 둘 다 기능적으로 동일합니다. 둘 다 조건부로 실행될 명령문 앞이나 뒤에 배치될 수 있습니다. Perl의 주요 디자이너이자 저자(Larry Wall)는 언어학자라고 추측할 수 있습니다.

에서 man perlsyn:

if조건이 참인 경우에만 명령문이 한 번 실행됩니다.

unless그렇지 않으면 조건이 true(즉, 조건이 false)가 아니면 명령문을 실행합니다.


이 조건은 {print; next}반드시 필요한 것은 아닙니다. 첫 번째 줄이나 마지막 줄이 두 번 인쇄되는 것을 방지하기 위한 것입니다.아니요"제목" 또는 "예고편"을 포함합니다. 이런 일이 절대 발생하지 않을 것이라고 확신한다면 첫 번째 명령문을 다음과 같이 약간 단순화할 수 있습니다.

첫 번째 단일 줄의 경우:

print if ($. == 1 || eof);

또는 (두 번째 행의 경우):

print if ($. == 1 || (! @ARGV && eof));

관련 정보