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.txt
file11.txt
에서 정렬하지 않으려면 쉘이 필요합니다 )file1.txt
file2.txt
zsh
또는 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
현재 라인이 첫 번째 입력 라인인지 테스트합니다.(! @ARGV && eof)
현재 줄이 마지막 파일의 마지막 줄인지 테스트합니다.스칼라 컨텍스트에서 평가하면
@ARGV
명령줄 인수(파일 이름) 배열의 요소 수가 반환되고, 각 파일 이름은shift
처리를 위해 열릴 때 배열에서 제거되어 개수가 줄어듭니다. 마지막 파일의 결과는 0(false)이 됩니다.!
마지막 파일을 읽을 때 이를 부정하면 ,AND 연산
eof
(현재 파일의 끝이면 true)은 마지막 파일의 마지막 행에서만 true입니다.
조건 중 하나가 true이면 현재 행을 인쇄합니다.
두 번째 문은 "Header" 또는 "Trailer"와 일치하지 않는 한 현재 줄을 인쇄합니다.
그런데, unless
Perl 구문은 ("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));