grep を使用して、パターンに一致する最初の行のすべての行を別のパターンとして返す

grep を使用して、パターンに一致する最初の行のすべての行を別のパターンとして返す

複数のファイルを検索していて、各行のヘッダーとして表示するファイル名が必要なので、grepを使用する必要があると思います。 macOSで端末を使用しています。

「dir」ディレクトリに次の内容を含むfile1ファイルがあるとします。

>species one; trnF(ggc)
GGCCC
AACGC
>species one; rrnS
TAGCA
GGCAC

"dir"ディレクトリには追加のファイルfile2もあり、その内容は次のとおりです。

>species two; trnF(gga)
GGACG
CGACG
GCAC
>species two; rrnS
GCATG
GGCAG

次の出力を取得したい。

dir/file1:>species one; trnF(ggc)
dir/file1-GGCCC
dir/file1-AACGC
--
dir/file2:>species two; trnF(gga)
dir/file2-GGACG
dir/file2-CGACG
dir/file2-GCAC

-Aを使用して、パターンのある行の後に指定された特定の数の行を取得できます。

$ grep -A 2 'trnF' dir/file*

ただし、これらのファイルはgrepコマンド以降の行数が異なるため、次のような結果が得られます。

dir/file1:>species one; trnF(ggc)
dir/file1-GGCCC
dir/file1-AACGC
--
dir/file2:>species two; trnF(gga)
dir/file2-GGACG
dir/file2-CGACG

次の「>」記号まですべてをどのように取得できますか?

答え1

見つかったように、grep -A静的な数のコンテキスト行だけを指定できるため、柔軟ではありません。

awk代わりに、選択したシーケンスが発生するタイミングを検出し、条件と一致しない他のシーケンスヘッダが見つかるまでそれを出力するコマンドは次のとおりです。

awk -v name='trnF' -v OFS=':\t' '
    FNR == 1 && NR > 1 { print "--" }
    /^>/ { out=0 }
    $0 ~ "^>.*" name { out=1 }
    out == 1 { print FILENAME, $0 }' files

このオプションはコードの変数に-v name=something割り当てられ、指定された文字列を含むfastaヘッダー行と一致する正規表現の一部として使用されます。somethingnameawk

最後の段落の出力はawk次のとおりです。

file:   >species one; trnF(ggc)
file:   GGCCC
file:   AACGC
--
file1:  >species one; trnF(ggc)
file1:  GGCCC
file1:  AACGC
--

:次のタブはファイル名とデータの区切り文字として使用され、OFSコマンドラインで別の項目に設定することで変更できます-v OFS=somethingelse。)

答え2

#! /bin/bash

for i in dir/file*
do
    [ -n "$is_first_file" ] && echo
    awk -v filename="$i" 'BEGIN { temp=1 }  { if ($1 ~ /^>/ && temp == 0){exit} } {if ( $1 ~ /^>/ && temp == 1 ) {print filename,"\b:","\b"$0,temp=0 } else { print filename,"\b-","\b"$0 }}' "$i"
    echo -n '--'
    is_first_file=no
done
echo -n -e "\b\b"

これについての経験はあまりありませんが、これはawkあなたが望む正確な結果を提供すると思います。

これも私がよく犯す間違いです。このスクリプトをそのように実行しないでくださいsh script_name

必要な-e場所に使用されます。echobash

./script_nameまたは同様に実行してくださいbash script_name

関連情報