
私のフォルダに12,000個のファイルがあり、大きなファイルにcsplitを使用しているため、同様の命名規則があります。ファイルの最初の行に基づいてこれらのファイルを並べ替えてから、同様のファイルをリンクする必要があります。
各ファイルの最初の行は「> 1」、「> 2」、「> 3」、または「> 4」で始まるため、最終的にすべての「> 4」ファイルは1つの凝集ファイルで終わる必要があります。この> 4ヘッダーを削除する必要はありません)
例:
ファイルxx1 xx3000とxx449は次のとおりです。
> 4 speciesX1
ATGC
私はそれを次のように見せるべきです。
> 4 speciesX1
ATGC
> 4 speciesX3000
ATGC
> 4 speciesX449
ATGC
sed -n -e '/> 4/,/>/ p' big_file >speciesX.txt を使用して元のファイルを分割しようとしましたが、目的のチャンクが印刷されなかったので、誰でも私を助けることができますか?
答え1
awk 'FNR==1 && ! /^> 4/ {nextfile}1' * > speciesX.txt
現在のファイルが最初の行で始まらない場合は、次のファイルに移動します> 4
。他のすべての行は標準出力として印刷されます。 stdoutはspeciesX.txt
シェルによってリダイレクトされます。
注:1
スクリプトの最後にtrueと評価、awkの基本操作を実行します(現在の行印刷)。awk
awkスクリプトは基本的にtest-condition { action-if-true }
テスト条件や操作を省略できる一連のルールなので、これは一般的な慣用語です。テスト条件がない場合は常に対応するアクションが実行され、アクションがない場合はprint
デフォルト値が使用されます。
上記の行を一致などに合わせて変更して実行するたびに別のファイルにリダイレクトするのは簡単ですが、すべての/^> 1/
入力/^> 2/
ファイルの出力ファイルを一度に作成し、スクリプトを一度だけ実行するには、次のようにします。物事:
awk 'FILENAME ~ /\.out$/ {nextfile};
FNR==1 && ! /^> [0-9]/ {nextfile};
FNR==1 {outfile=$2 ".out"};
{print > outfile}' *.txt
まず、現在の入力ファイルがで終わっていることを確認してください.out
。その場合は、次のファイルにジャンプします。すべての入力ファイルがたとえば終わる場合は必要ありませんが、.txt
それが本当かどうかはわかりません(言わなかった)、そのケースを適切に処理する方が良いでしょう。
>
次に、各ファイルの最初の行を確認し、許容可能なパターン(たとえば、「で始まり、スペース、数字が続きます」)と一致しない場合は、次のファイルに移動します。
それ以外の場合は、出力ファイル名を設定するために、最初の行の2番目のフィールドに「.out」が追加されます。
これにより、入力の各行が出力ファイル名で印刷されます。ファイル、、、1.out
などで終わります。後で を使用して名前を変更できます。2.out
3.out
4.out
mv
awkでのリダイレクトはシェルとは少し異なり>
ます。>>
- シェルは既存のファイルを削除して上書きします。
>
使用するたびに(ファイルに追加を使用する必要があります>>
)。 - awkはファイルを削除して上書きします。ただ最初ファイル名が表示されます単一スクリプト実行内で、後続のすべての出力は同じファイル名に追加されます(同じスクリプト実行内)。
>>
これにより、スクリプトが最初にファイル名を解決した場合でも、削除と上書きを防ぎます。つまり、常に追加されます。
ちなみに、スクリプトの最後の行は{print > outfile}
テスト条件なしでアクションを実行するawkルールの例です。これは各入力行に対して行われます(前の規則が次の行またはファイルと同様に機能するnext
か、すぐにジャンプしない限り)。nextfile
答え2
この試み:
IFS=$'\n' i=1; for header in $(egrep -m1 '> [0-9]' * -oh | sort | uniq); do grep -rl "$header" . | xargs -I{} cat {} >> file${i}; ((i++)); done
12000個のファイルを含むディレクトリでこのコマンドを実行すると、file1、file2、file3などの別々のファイルが作成されます。各ファイルには、("> 1"、"> 2"で始まる同じヘッダーを持つリンクファイルが含まれています。)すべてのファイルが一緒にあります。
説明する:
egrep -m1 '> [0-9]' * -oh | sort | uniq - find all headers starting with "> number" ("> 1", "> 2") and remove duplicates.
IFS=$'\n' i=1; for header in $(...); do ...; done - iterate over the list of headers.
grep -rl "$header" . | xargs -I{} cat {} >> file${i}; ((i++)); - for each header concat all files started by the header to a separate file.