文字列/ファイル名が別々の行にあるテキストファイルがあります。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.txt
んresults.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.txt
(FNR
ファイルごとのラインカウンタはNR
グローバルラインカウンタと同じです)、すべてのファイル名を配列(ラインの唯一のフィールド)に登録しますfnames
が、すぐに次の実行ラインにジャンプします。 - 構文解析時
results.txt
に行が始まることを確認してください>
。その場合は、その文字の後の部分文字列(一時的に保存)がのname
「配列インデックス」にあることを確認してくださいfnames
。この場合、sub()
先行を+プレフィックスに置き換え、>
それを>
(指示文を介して)変数として渡します。awk
prefix
-v
- "stray"は、可能なすべての修正を含む現在の行を印刷するように
1
指示するようです(ただし、最初のファイルの処理中にそのセクションに到達できなかった場合にのみ)。awk
results.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;d
(1h
予約済みスペースが改行から始まるのを防ぐため)。 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