使用 grep、awk 和 csv 從文字檔案中提取訊息

使用 grep、awk 和 csv 從文字檔案中提取訊息

我正在使用以下程式碼從一堆文字檔案(foo*.txt)中提取資訊。

for file in foo*.txt; do 
grep "some_text" $file | tail -n5 | awk '{print $2}' >> bar.csv
done

此註釋列印我想要從一堆文件(foo*.txt)中獲得的數字。當我嘗試列印檔案名稱(在 csv 檔案的一列中)和數字(在 csv 檔案的下一列中)時,我嘗試在終端機上執行以下操作。

for file in foo*.txt; do 
echo $file
grep "some_text" $file | tail -n5 | awk '{print $2}' >> bar2.csv 
done

這會在終端機上列印文件的名稱。 csv 檔案包含我想要的數字。如何修改此程式碼,以便將檔案名稱列印在一個列上,並將提取的數字列印在 csv 檔案的下一列中?

這段程式碼中的另一個問題是排序問題。例如,考慮檔名 foo_01_s.txt、foo_02_s.txt、foo_03_s.txt.....foo_100_s.txt。如果我想提取資訊(使用上面的註解),最後一個檔案(foo_100_s.txt)不會出現在foo_99_s.txt之後。

使用 Python/Perl 的解決方案也會有所幫助。

答案1

您必須了解您的>>只會重定向當前命令的部分 - 基本上只是以 開頭的命令結果的數字grep,並通過管道傳輸幾次。echo $file是一個單獨的命令(您使用;),因此通常會定向到標準輸出。您需要做的就是在整個循環之後重定向:

for file in foo*.txt; do 
    echo $file
    grep "some_text" $file | tail -n5 | awk '{print $2}'
done > bar2.csv

如果您想對文件進行“版本”排序(這是合適的名稱),您可以在排序後列出它們:

for file in $(ls foo*.txt | sort -V); do

對於快速運行一些小東西(大約 1000 個文件只需幾分鐘),這應該沒問題。

編輯

根據您的評論,有一些解決方案。我猜你想要:

file1 1
      2
      3

等等echo

for file in foo*.txt; do 
    grep "some_text" $file | tail -n5 | awk -v f=$file '{if(NR==1) {printf("%-20s %-5s\n",f,\$2)} else {printf("%-20s %-5s\n","",$2)}}'
done > bar2.csv

我請awk他們幫我列印。使用-v允許我在 中傳遞變數f。對於列印,請熟悉printf語法(您可以man printf在 shell 中使用。基本上,我假設有兩個字段,一個是 20,另一個是 5,中間有一個空格。負號左對齊。您可以使用它。這將已經解決了您最初的問題,因為現在您可以透過管道傳輸該單行。

如果您希望該文件只是:

file1,1
file1,2
...
file2,1

您可以刪除if我的聲明中的awk,或者保留帶有 echo 的初始解決方案,但使用,

echo -n "$file,"

where-n確保不列印換行符號。

相關內容