10個のファイルを1つにマージする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
最初の文は2つの条件をテストします。
$. == 1
現在のラインが最初の入力ラインかどうかをテストします。(! @ARGV && eof)
現在の行が最後のファイルの最後の行であるかどうかをテストします。スカラーコンテキストで評価すると、コマンド
@ARGV
ライン引数(ファイル名)配列の要素数が返され、各ファイル名はshift
処理用に開かれると配列から削除され、数が減ります。最後のファイルの結果は0(false)になります。!
最後のファイルを読むときにそれを否定すると、AND 演算
eof
(現在のファイルの終わりの場合は true) は、最後のファイルの最後の行でのみ true です。
条件の1つがtrueの場合、現在の行を印刷します。
2番目のステートメントは、「Header」または「Trailer」と一致しない限り、現在の行を印刷します。
ちなみに、unless
Perlの構文は(「if not」)と同じですif !
。時々、「XでなければYを行います」と言う方が自然で、「XでなければYを行います」と言う方が自然です。どちらも機能的に同じです。どちらも条件付きで実行されるステートメントの前または後に配置できます。 Perlの主なデザイナーであり、著者(Larry Wall)は言語学者であると推測できます。
からman perlsyn
:
if
条件が真の場合にのみ、ステートメントが一度実行されます。
unless
それ以外の場合、条件がtrue(つまり、条件がfalse)でない場合はステートメントを実行します。
この条件は{print; next}
必ずしも必要ではありません。最初の行または最後の行が2回印刷されるのを防ぐためです。いいえ「タイトル」または「予告編」が含まれます。これが決して起こらないと確信している場合は、最初のステートメントを次のように少し単純化できます。
最初の単一行の場合:
print if ($. == 1 || eof);
または(2行目の場合):
print if ($. == 1 || (! @ARGV && eof));