文字列入力ファイルを読み、一致を実行し、一致を変更するにはどうすればよいですか?

文字列入力ファイルを読み、一致を実行し、一致を変更するにはどうすればよいですか?

文字列/ファイル名が別々の行にあるテキストファイルがあります。filename.txt。何百ものファイル名があります

ABC123_S386_R1_001
JKL345_S441_R1_001
filename9000_S587_R1_001

文字列/ファイル名と追加データを含む別のテキストファイル。results.txt:

>ABC123_S386_R1_001 
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>JKL345_S441_R1_001
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>abc7890_S387_R1_001  
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>filename9000_S587_R1_001
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN

これで、すべてのファイル名filename.txtがに表示されず、results.txt順番に表示されるわけでもありません。すべてのファイル名にプレフィックスを挿入したいのですが、他のファイル名には挿入しようとしませfilename.txtresults.txt

文字列入力ファイルを読み、他のファイルと一致させ、一致を変更するにはどうすればよいですか?

以前は、個々のファイル名を一致させてsequence.txt行番号を取得し、sedそれを行番号と一緒に使用して1行または行ブロックを変更しました。

私が望む出力は次のとおりです。

>h-19/US/CA-ABC123_S386_R1_001 
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>h-19/US/CA-JKL345_S441_R1_001
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>abc7890_S387_R1_001  
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>h-19/US/CA-filename9000_S587_R1_001
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN

h-19/US/CA-すべての一致に追加したいサフィックスはどこにありますか?

編集:>変更する必要があるすべての文字列の最初の文字で、前に文字がなく、>ファイル名の後にスペースがありません。

答え1

results.txtファイル名の後の関連行にスペースが含まれていないと仮定すると、次のawkプログラムが機能します。

awk -v prefix="h-19/US/CA-" 'NR==FNR{fnames[$1]; next} \
    /^>/{name=substr($0,2); if (name in fnames) {sub(/^>/, ">" prefix)} }1' filenames.txt results.txt
  • filenames.txtその後、まず解析が実行されますresults.txt
  • 解析中filenames.txtFNRファイルごとのラインカウンタはNRグローバルラインカウンタと同じです)、すべてのファイル名を配列(ラインの唯一のフィールド)に登録しますfnamesが、すぐに次の実行ラインにジャンプします。
  • 構文解析時results.txtに行が始まることを確認してください>。その場合は、その文字の後の部分文字列(一時的に保存)がのname「配列インデックス」にあることを確認してくださいfnames。この場合、sub()先行を+プレフィックスに置き換え、>それを>(指示文を介して)変数として渡します。awkprefix-v
  • "stray"は、可能なすべての修正を含む現在の行を印刷するように1指示するようです(ただし、最初のファイルの処理中にそのセクションに到達できなかった場合にのみ)。awkresults.txt

awkそれ自体はファイルを変更できないため、一時ファイルを使用する必要があります。最新バージョンのGNU Awk(> 4.1.0)がある場合は、もちろん拡張機能を使用できます。ファイルオプションをオフにする必要がinplaceあります。filenames.txt

awk -i inplace -v prefix=" ... " ' ... ' inplace=0 filenames.txt inplace=1 results.txt

filenames.txtこれにより、内部編集が閉じて再び開きますresults.txt

答え2

予約済みスペースからファイル名を収集し、すべての行が一致sedするresults.txtことを確認し、変更したい行をフィルタリングできます。

sed -e '1,/^$/{H;1h;d;}' -e 'G;/^>\(.*\).*\n\1\n/s_^>_>h-19/US/CA-_;P;d' filename.txt <((echo)) results.txt
  • <((echo))ファイル間に空白行を渡すことで、1,/^$/最初のファイルのすべての行(空白行を含む)が解決されたことがわかります。
  • 行は予約済みスペースに追加され、削除されますH;1h;d1h予約済みスペースが改行から始まるのを防ぐため)。
  • Gすべての行に予約済みスペースを追加してresult.txtから/^>\(.*\).*\n\1\n/始まる行と一致します>。文字列はファイル名です(予約済みスペースの改行文字に含まれています)。
  • s_^>_>h-19/US/CA-_このラインを交換する必要がありますか?
  • P;d追加のゴミなしで最初の行だけが印刷されます。あなたはs/\n.*//これを行うことができます

答え3

perl入力ファイルを内部編集する場合:

pfx='h-19/US/CA-' \
perl -pi -e '
  BEGIN { %h = map { tr/\n//dr => $ENV{pfx}} <STDIN>}
  s/^>\K(?=(.*))/$h{$1}/;
' results.txt < filename.txt

関連情報