2016-05-26 17 views
2

重新創建上一個問題以便更清楚。我試圖搜索兩個目錄中的文件,並且只有匹配第一個目錄中的記錄時,纔會將匹配的字符串(緊隨其後的一行)打印到第二個目錄中的新文件中。我發現了類似的例子,但沒有什麼不同。我不知道如何使用awk來處理來自不同目錄的多個文件,並且我折磨自己試圖找出它。如何在兩個目錄中使用awk進行多個文件搜索,僅從第二個目錄中匹配字符串的文件中打印記錄

目錄1,28,000個文件,格式化爲即,

>ABC 
KLSDFIOUWERMSDFLKSJDFKLSJDSFKGHGJSNDKMVMFHKSDJFS 
>GHI 
OOILKJSDFKJSDFLMOPIWERIOUEWIRWIOEHKJTSDGHLKSJDHGUIYIUSDVNSDG 

目錄2,15個文件,格式化

>ABC 
12341234123412341234123412341234123412341234123412341234123412341234 
>DEF 
12341234123412341234123412341234 
>GHI 
12341234123412341234123412341234123412341234123412341234123412341234123412341234 

所需的輸出:

>ABC 
12341234123412341234123412341234123412341234123412341234123412341234 
>GHI 
12341234123412341234123412341234123412341234123412341234123412341234123412341234 

目錄1及2處位於我的主目錄:(./Test1 & ./Test2)

如果任何人都可以建議命令的具體不同的目錄,我會非常感激!目前,當我包括文件路徑(例如,/Test1/*.fa)我得到以下錯誤:

awk: can't open file /Test1/*.fa 

回答

0

你會想是這樣的(未經測試):

awk ' 
FNR==1 { 
    dirname = FILENAME 
    sub("/.*","",dirname) 
    if (NR==1) { 
     dirname1 = dirname 
    } 
} 
dirname == dirname1 { 
    if (FNR % 2) { 
     key = $0 
    } 
    else { 
     map[key] = $0 
    } 
    next 
} 
(FNR % 2) && ($0 in map) && !seen[$0,map[$0]]++ { 
    print $0 ORS map[$0] 
} 
' Test1/* Test2/* 

給你」再次收到錯誤消息/usr/bin/awk: Argument list too long這意味着you're exceeding your shells maximum argument length for a command和您的文件28000是在Test1的目錄,試試這個:

find Test1 -type f -exec cat {} \; | 
awk ' 
NR == FNR { 
    if (FNR % 2) { 
     key = $0 
    } 
    else { 
     map[key] = $0 
    } 
    next 
} 
(FNR % 2) && ($0 in map) && !seen[$0,map[$0]]++ { 
    print $0 ORS map[$0] 
} 
' - Test2/* 
+1

到目前爲止似乎正在工作 - 在我的筆記本電腦上進行測試的文件數量減少了 - 將在我明天回到辦公室時檢查完整數據集並跟進 - 非常感謝您! – MoGo

+0

我不得不說,得說 - 這真是太棒了!我只遇到一個掛斷,這是我的完整數據集提供了一個錯誤「/ usr/bin/awk:參數列表太長」。我試圖把它變成'xargs',我得到了同樣的錯誤。我已經將> 28,000個文件複製到另一個目錄中,以較慢的方式執行此操作,但我想問問是否有其他技巧可以解決此問題?只是爲未來的努力添加另一個信息資源(這是一個我會更經常使用的腳本)。 – MoGo

+0

你超出了shell的最大參數長度,因此你會得到與任何命令(ls,cat,xargs等)相同的錯誤。讓我想想看,如果我能想出一個解決方法(谷歌的結果在這種情況下沒有產生任何有用的東西)。 –

0

解決方案在TXR

數據:

 
$ ls dir* 
dir1: 
file1 file2 

dir2: 
file1 file2 

$ cat dir1/file1 
>ABC 
KLSDFIOUWERMSDFLKSJDFKLSJDSFKGHGJSNDKMVMFHKSDJFS 
>GHI 
OOILKJSDFKJSDFLMOPIWERIOUEWIRWIOEHKJTSDGHLKSJDHGUIYIUSDVNSDG 

$ cat dir1/file2 
>XYZ 
SDOIWEUROIUOIWUEROIWUEROIWUEROIWUEROUIEIDIDIIDFIFI 
>MNO 
OOIWEPOIUWERHJSDHSDFJSHDF 

$ cat dir2/file1 
>ABC 
12341234123412341234123412341234123412341234123412341234123412341234 
>DEF 
12341234123412341234123412341234 
>GHI 
12341234123412341234123412341234123412341234123412341234123412341234123412341234 

$ cat dir2/file2 
>STP 
12341234123412341234123412341234123412341234123412341234123412341234123412341234 
>MNO 
123412341234123412341234123412341234123412341234123412341234123412341234 
$ 

運行:

 
$ txr filter.txr dir1/* dir2/* 
>ABC 
12341234123412341234123412341234123412341234123412341234123412341234 
>GHI 
12341234123412341234123412341234123412341234123412341234123412341234123412341234 
>MNO 
123412341234123412341234123412341234123412341234123412341234123412341234 

守則filter.txr

@(bind want @(hash :equal-based)) 
@(next :args) 
@(all) 
@dir/@(skip) 
@(and) 
@ (repeat :gap 0) 
@dir/@file 
@ (next `@dir/@file`) 
@ (repeat) 
>@key 
@  (do (set [want key] t)) 
@ (end) 
@ (end) 
@(end) 
@(repeat) 
@path 
@ (next path) 
@ (repeat) 
>@key 
@datum 
@ (require [want key]) 
@ (output) 
>@key 
@datum 
@ (end) 
@ (end) 
@(end) 

從靜止分離dir1路徑,我們使用了一個@(all)匹配(嘗試多模式分支,必須全部匹配)與兩個分支。第一個分支匹配一個@dir/@(skip)模式,將變量dir綁定到以斜槓開頭的文本,並忽略其餘部分。第二個分支通過@(repeat :gap 0)匹配整個連續的@dir/@file模式序列。因爲同一個dir變量顯示已具有來自all的第一個分支的綁定,所以這會將匹配限制爲相同的目錄名稱。在repeat的內部,我們通過next遞歸到每個文件中,並將>限定的密鑰收集到keep哈希中。之後,我們將剩餘的參數作爲待處理文件的路徑名處理;他們並不都必須在同一個目錄中。我們掃描每一個的>@key模式,後面跟着一行@datum。如果key不在wanted散列中,則@(require ...)指令將會使匹配失敗,否則我們將跳轉到@(output)

+0

非常感謝!剛到那天晚上,但將在辦公室早上檢查這個第一件事並跟進 - 我非常感謝您對語法的全面解釋。我之前沒有使用過TXR--一些新的東西可以學習,並且你的註釋很好的解決方案將使我的曲目更容易添加! – MoGo

相關問題