同じヘッダーとその下の異なるベクターを持つ複数のファイルがあります。すべてを連結する必要がありますが、最初のファイルのヘッダーのみを連結したいのですが、他のヘッダーはすべて同じなので連結したくありません。
例:file1.txt
<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B
C
file2.txt
<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
D
E
F
私は出力が必要です
<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B
C
D
E
F
Rでスクリプトを記述できますが、シェルで必要ですか?
Rでそれを行う方法を知っている場合は、必ずRで実行してください。従来のUNIXツールでは、これは最も自然にawkで行われます。
_awk '
FNR==1 && NR!=1 { while (/^<header>/) getline; }
1 {print}
' file*.txt >all.txt
_
Awkスクリプトの最初の行は、すべてのファイル(_FNR==1
_)の最初の行でもある場合を除いて、ファイル(_NR==1
_)の最初の行と一致します。これらの条件が満たされると、式while (/^<header>/) getline;
が実行されます。これにより、現在の行が正規表現_^<header>
_に一致する限り、awkは別の行を読み取り続けます(現在の行をスキップします)。 awkスクリプトの2行目は、以前にスキップされた行を除くすべてを出力します。
tail
とhead
を使用した、上記の「cat+grep
」と同様の別のソリューション:
最初のファイルのヘッダーを出力に書き込みます。
head -2 file1.txt > all.txt
-head -2
は、ファイルの最初の2行を取得します。
すべてのファイルの内容を追加します。
tail -n +3 -q file*.txt >> all.txt
--n +3
は、3行目から最後までtail
印刷行を作成し、-q
は、ヘッダーをファイル名で印刷しないように指示します(man
を読み取る)、>>
はファイルに追加し、>
として上書きしません。
そして、両方のコマンドを1行で入力できることを確認してください。
head -2 file1.txt > all.txt; tail -n +3 -q file*.txt >> all.txt
または;
の代わりに、成功チェックのためにそれらの間に&&
を挿入します。
これを試してください:
$ cat file1.txt; grep -v "^<header" file2.txt
<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B
C
D
E
F
-v
フラグは grep の一致を反転することを意味します^
in [〜#〜] regex [〜#〜] 、は文字列の始まりを意味します:
array=( files*.txt )
{ cat ${array[@]:0:1}; grep -v "^<header" ${array[@]:1}; } > new_file.txt
bash 配列スライステクニックです。
sed
を使用すると、短い(必ずしも速いとは限りません):
sed -e '3,${/^<header>/d' -e '}' file*.txt > all.txt
これにより、3行目から始まる<header>...
で始まるすべての行が削除されるため、最初のヘッダーは保持され、他のヘッダーは削除されます。ヘッダーの行数が異なる場合は、それに応じてコマンドを調整します(たとえば、6行のヘッダーの場合、7
ではなく3
を使用します)。
ヘッダーの行数が不明な場合は、次のように試すことができます。
sed '1{
: again
n
/^<header>/b again
}
/^<header>/d
' file*.txt > all.txt
tail
コマンド(少なくともGNUでは)には、指定された数の最初の行をスキップするオプションがあります。 2行目以降を印刷するには、つまり1行のヘッダーをスキップするには、次のようにします。tail -n+2 myfile
したがって、Bashで最初のファイルの2行のヘッダーを保持し、2番目のファイルのヘッダーを保持しないようにするには、次のようにします。
cat file1.txt <(tail -n+3 file2.txt) > combined.txt
または、多くのファイルの場合:
head -n1 file1.txt > combined.txt
for fname in *.txt
do
tail -n+3 $fname >> combined.txt
done
特定の文字列がすべてのヘッダー行に存在するが、残りの入力ファイルには存在しないことがわかっている場合、grep -v
は、スプートニクが示したように、より単純なアプローチです。
array =(* .txt); head -1 $ {array [0]}> all.txt;尾-n +2 -q $ {array [@]:0} >> all.txt
結合/連結が必要な同じヘッダーの.txtファイルを含むフォルダーを使用していると仮定すると、このコードは、txtファイルをすべて1つのヘッダーだけでall.txtに結合します。最初の行(セミコロンで区切られた行)はすべてのテキストファイルを収集して連結し、2行目は最初のtxtファイルのヘッダーをall.txtに出力し、最後の行は収集したすべてのテキストファイルを連結しますヘッダーなしで(2行目以降から連結を開始することにより)、それをall.txtに追加します。