ファイル名の一部をパターンとして使用して複数のファイルを grep するにはどうすればよいでしょうか?

ファイル名の一部をパターンとして使用して複数のファイルを grep するにはどうすればよいでしょうか?

フォルダには、文字列であるorder[ID].log名前の付いた複数のファイルが含まれています。[ID]

orderID1.log
orderID2.log
orderID3.log
orderID4.log
...

grepLinuxで各ファイルにスクリプトを記述しID、結果をという名前のファイルに出力する必要がありますID.log 。例:
の場合orderID1.log、 の場合、 が必要です。grep 'ID1' orderID1.log > ID1.log
の場合orderID2.log、 が必要ですgrep 'ID2' orderID2.log > ID2.log
。以下のスクリプトを記述しようとしました。

for i in ORDER*.log 
do 
grep 'i' order$i > $i.log;
done

ここでの問題は、「ID1」、「ID2」ではなく、「orderID1」、「orderID2」として記録されることです。 Linux でこれを行う簡単な方法はありますか?

答え1

IDファイル名から部分文字列を抽出する必要があります。これを行う 1 つの方法は、パラメータ展開を使用することです。${var:offset:length}たとえば、この場合、varfilename、オフセットは5( order)、長さは${#f}-9(つまり、${#f}合計長から と の合計order長 (文字数) を引いた値).logです9

for f in order*.log                                                 
  do 
    ID=${f:5:${#f}-9}
    grep -- "$ID" "$f" > "$ID".log
  done

またはワンライナーを好む場合は:

for f in order*.log; do ID=${f:5:${#f}-9}; grep -- "$ID" "$f" >" $ID".log; done

あるいはawk複数のファイルに対して同じアクションを実行する:

awk '
FNR==1{
if(fname)close(fname)
id=substr(FILENAME, 6, length(FILENAME)-9)
fname=id".log"
}
$0 ~ id{
print > fname
}
' order*.log

awkこれは、シェル ループを回避して、1 回の呼び出しですべてのファイルを実行します。1 行で次のようになります。

awk 'FNR==1{if(f)close(f);id=substr(FILENAME, 6, length(FILENAME)-9);f=id".log"} $0~id{print > f}' order*.log

関連情報