it-swarm.com.de

Wie verwende ich Dateinamen in einem sed-Befehl?

Ich habe eine Reihe von .conf Dateien, die identisch sind und sich im selben Verzeichnis befinden, mit der Ausnahme, dass sie unterschiedliche Dateinamen haben. In jeder Datei mit dem eindeutigen Namen .conf möchte ich einen Zeichensatz in der Datei durch den Namen der Datei ersetzen. Zum Beispiel:

Derzeit in allen Dateien:

datafname = example.nex
ofprefix = best.example

Ideale Leistung:

Dateiname: 25.conf

datafname = 25.nex
ofprefix = best.25

Dateiname: 26.conf

datafname = 26.nex
ofprefix = best.26

Ich dachte, ich könnte sed verwenden, um alle diese Dateien zu durchsuchen und die Zeichenfolge mit dem Dateinamen zu suchen und zu ersetzen.

sed -i conf 's/example/echo $f/g' *

aber das funktioniert nicht richtig. Würde jemand einen Vorschlag dazu haben?

6
foolsparadise

Du kannst tun:

for f in *.conf; do
    base=$(basename "$f" '.conf') # gives '25' from '25.conf'
    sed -i.before "s/example/$base/g" "$f"
done

Wenn Sie den Schalter -i auf sed stellen, müssen Sie absolut sicher sein, dass Ihr Befehl sed funktioniert, da -i die Dateien ändert an Ort und Stelle. Dies bedeutet, dass die generierte Ausgabe die Eingabedatei überschreibt. Wenn Ihr Ersetzungsbefehl (s/…/…/) falsch ist, erhalten Sie möglicherweise leere Dateien und keine Sicherungen. Daher habe ich -i.before verwendet, wodurch eine *.before -Datei mit dem ursprünglichen Inhalt zurückbleibt.

8
PerlDuck

Sie können eine for-Schleife verwenden, um die Dateien zu durchlaufen. Verwenden Sie die Parametererweiterung, um die Dateierweiterung zu entfernen. Verwenden Sie doppelte Anführungszeichen um den Ausdruck, sonst würde die Variable nicht erweitert.

#! /bin/bash
for f in *.conf ; do
    b=${f%.conf}
    sed -i "s/example/$b/" "$f"
done
5
choroba

Sie können die Aufgabe auch ohne Schleife ausführen, indem Sie GNU parallelInstall parallel :

parallel sed -i.old s/example/{.}/ {} ::: *.conf

Dies ist besonders nützlich, wenn Sie eine Menge Dateien bearbeiten müssen, da parallel einen Job pro CPU-Kern ausführt.

  • -i.old bedeutet: Bearbeiten Sie die Datei in-place und erstellen Sie eine Sicherungskopie, indem Sie die Erweiterung .old zum ursprünglichen Dateinamen hinzufügen (entfernen Sie .old, wenn Sie keine Sicherungskopie erstellen möchten, aber Denken Sie daran, dass Sie dann kein Backup haben)
  • s/example/{.}/g bedeutet substitute example mit dem eingegebenen Dateinamen ohne dessen Erweiterung ({.}) und mache es globally (= für jedes Vorkommen)
  • {} wird durch den eingegebenen Dateinamen ersetzt
  • ::: trennt den auszuführenden Befehl von den Argumenten, die an ihn übergeben werden sollen
  • *.conf entspricht jeder .conf Datei im aktuellen Verzeichnis
2
dessert

Mit awk, bei dem die Variable FILENAME automatisch auf den Dateinamen gesetzt wird (und, falls GNU awk, auch mit vorhandenen Änderungen):

$ for i in {20..26}; do printf "%s\n" "datafname = example.nex" "ofprefix = best.example" > $i.conf; done
$ gawk -i inplace 'FNR == 1 {split(FILENAME, file, ".")} {gsub("example", file[1])} 1' *.conf
$ cat 25.conf
datafname = 25.nex
ofprefix = best.25
  • FNR == 1 {split(FILENAME, file, ".")}: Teilen Sie in der ersten Zeile jeder Datei den Dateinamen in . und speichern Sie ihn im Array file
  • {gsub("example", file[1])} 1: Ersetzen Sie example für alle Zeilen durch das erste Element des Arrays file und drucken Sie.
1
muru