我有一個文字文件,其中字串/文件名位於單獨的行中,例如。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
與行號一起使用來更改單行或行塊。
我想要的輸出看起來像
>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
- 看似「雜散」
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