Wie kann ich mehrere Dateien greppen, indem ich einen Teil des Dateinamens als Muster verwende?

Wie kann ich mehrere Dateien greppen, indem ich einen Teil des Dateinamens als Muster verwende?

Ich habe einen Ordner, der mehrere Dateien mit dem Namen enthält, order[ID].logwobei es [ID]sich um eine Zeichenfolge handelt, z. B.

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

grepIch muss in Linux ein Skript für jede Datei mit dem in ihrem Namen schreiben IDund das Ergebnis in eine Datei mit dem Namen ausgeben. ID.log Beispiel:
Für orderID1.logmuss ich grep 'ID1' orderID1.log > ID1.log
Für orderID2.logmuss ich Ich habe grep 'ID2' orderID2.log > ID2.log
versucht, das folgende Skript zu schreiben.

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

Das Problem hier ist, dass ich als „orderID1“, „orderID2“ und nicht als „ID1“, „ID2“ aufgezeichnet werde. Gibt es eine einfache Möglichkeit, dies unter Linux zu tun?

Antwort1

Sie müssen die IDTeilzeichenfolge aus den Dateinamen extrahieren. Eine Möglichkeit hierfür ist die Parametererweiterung. ${var:offset:length}In Ihrem Fall varlautet also filename, offset ist 5( order) und length ist ${#f}-9(also die Gesamtlänge ${#f}abzüglich der kombinierten Länge von orderund , .logdie Zeichen sind 9):

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

oder wenn Sie einen Einzeiler bevorzugen:

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

Alternativ können Sie sich auch awkbewerben mitdie gleiche Aktion für mehrere Dateien:

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

Dies führt alle Dateien mit einem awkAufruf aus und vermeidet die Shell-Schleife. In einer Zeile:

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

verwandte Informationen