
Ich habe einen Ordner, der mehrere Dateien mit dem Namen enthält, order[ID].log
wobei es [ID]
sich um eine Zeichenfolge handelt, z. B.
orderID1.log
orderID2.log
orderID3.log
orderID4.log
...
grep
Ich muss in Linux ein Skript für jede Datei mit dem in ihrem Namen schreiben ID
und das Ergebnis in eine Datei mit dem Namen ausgeben. ID.log
Beispiel:
Für orderID1.log
muss ich grep 'ID1' orderID1.log > ID1.log
Für orderID2.log
muss 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 ID
Teilzeichenfolge aus den Dateinamen extrahieren. Eine Möglichkeit hierfür ist die Parametererweiterung. ${var:offset:length}
In Ihrem Fall var
lautet also f
ilename, offset ist 5
( order
) und length ist ${#f}-9
(also die Gesamtlänge ${#f}
abzüglich der kombinierten Länge von order
und , .log
die 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 awk
bewerben 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 awk
Aufruf 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