2017-08-25 84 views
0

得到輸入和輸出文件名信息我有一個名爲「names.txt中」文件,其中包含一個字符串列表:AWK:從文件

apple 
banana 
orange 

而且我有一個包含包含字符串的文件名的目錄這是在「names.txt中」上市:

apple_file.txt 
orange_file.txt 
banana_file.txt 

我想對所有在該目錄包含在「names.txt中」字符串中的文件執行awk命令,以「_file.txt」結束,將新的輸出文件保存爲包含相同字符串並以「_better_file.txt」結尾的文件,所以基本上這三個WK命令執行:

awk '{print $1,$3}' apple_file.txt > apple_better_file.txt 
awk '{print $1,$3}' banana_file.txt > banana_better_file.txt 
awk '{print $1,$3}' orange_file.txt > orange_better_file.txt 

如何更有效地比三個AWK使用文件「names.txt中」上面的命令做任何想法?

+0

**有效率**你的意思是更少的過程或更少的代碼? – Kent

+0

我的意思是使用一個單一的命令,該命令使用現在在我的示例解決方案中未使用的輸入文件「names.txt」。有數百個文件,而不僅僅是我給出的三個例子。 – Abdel

+1

爲什麼你需要names.txt而不是僅僅在* _file.txt上運行?是否有一些你不想操作的* _file.txt文件,所以names.txt是一個子集?在$(cat names.txt)中用於f的 –

回答

1

您可以遍歷文件以將awk命令應用於每個文件。

使用for f in $(cat names.txt); do awk '{ print $1,$3 }' ${f}_file.txt > ${f}_better_file.txt; done,它提供了:

# cat names.txt 
apple 
banana 
orange 
# ls -1 *_file.txt 
apple_file.txt 
banana_file.txt 
orange_file.txt 
# for f in $(ls -1 *_file.txt); do echo $f; cat $f; done 
apple_file.txt 
foo bar foo 
aze rty aze 
foo bar foo 
banana_file.txt 
foo bar foo 
aze rty aze 
foo bar foo 
orange_file.txt 
foo bar foo 
aze rty aze 
foo bar foo 
# for f in $(cat names.txt); do awk '{ print $1,$3 }' ${f}_file.txt > ${f}_better_file.txt; done 
# for f in $(ls -1 *_better_file.txt); do echo $f; cat $f; done 
apple_better_file.txt 
foo foo 
aze aze 
foo foo 
banana_better_file.txt 
foo foo 
aze aze 
foo foo 
orange_better_file.txt 
foo foo 
aze aze 
foo foo 
# 

或者,也許你只想AWK使用?在這種情況下,迴路解決方案將不符合。

+0

; awk'{print $ 1,$ 3}'$ {f} _file.txt> $ {f} _better_file。文本; done'有多個基本的shell編程錯誤(UUOC,非引用變量,用於$(command output)中的f)。真正寫這個循環的方法是'while IFS = read -r f; awk'{print $ 1,$ 3}'「$ {f} _file.txt」>「$ {f} _better_file.txt」;完成

+0

wrt'for f in $(ls-1 * _better_file.txt)' - 想想這是幹什麼的,而不是僅僅爲了''_better_file.txt'中的f。 [谷歌「解析ls輸出」](https://www.google.com/search?q=parse+ls+output&ie=utf-8&oe=utf-8),特別是閱讀http://mywiki.wooledge.org/ParsingLs。 –

+1

我會閱讀你的文檔,感謝你的鏈接。這是一個循環文件​​解決方案的POC,而不是複製粘貼到prod命令。 –

1

試一試,awk單線程,單進程,不循環。

awk 'NR==FNR{a[$0"_file.txt"]=$0"_better_file.txt";next} 
    a[FILENAME]{print $1,$3 >> a[FILENAME] }' names.txt *_file.txt 

希望它給你想要的。

+1

只有在文件名以'0 ...'開頭的情況下,你才應該在''FILENAME'而不是'[FILENAME]中進行測試。 ITYM'''btw,而不是'>>' - awk不是shell。 –

1
awk ' 
NR==FNR{ ARGV[ARGC]=$0"_file.txt"; ARGC++; next } 
FNR==1 { close(out); out=FILENAME; sub(/_[^_]+$/,"_better&",out) } 
{ print $1, $3 > out } 
' names.txt 

中相應的NR == FNR塊上方讀取「names.txt中」,以及用於在names.txt中每一行「foo」的它添加一個條目「foo_file.txt」到的所述陣列的所述端腳本將在其上運行的文件名(ARGV [])。

NR == FNR塊之後的部分是對這些「foo_file.txt」文件中的每一個進行操作,並且步驟1是關閉任何之前打開的輸出文件(如果有的話),以避免出現「太多打開文件「錯誤,然後通過在當前輸入文件名中間添加」_better「來創建一個新的輸出文件名,所以給定輸入文件名」foo_file.txt「它會創建一個輸出文件名」foo_better_file 。文本」。

然後最後一行簡單地將您感興趣的2個字段從輸入文件打印到輸出文件中。

1

假設的任何數量的從names.txt中包含字符串,並用 「_file.txt」(可能不是強制性的與apple_前綴,orange_等)結尾的文件的:

for f in $(grep -lf names.txt *_file.txt); do awk '{print $1,$3}' "$f" > "${f/_file/_better_file}"; done