Wie verwende ich Dateinamen in einem sed-Befehl?


7

Ich habe eine Reihe von .confDateien, die identisch sind und sich im selben Verzeichnis befinden, mit Ausnahme unterschiedlicher Dateinamen. In jeder eindeutig benannten .confDatei möchte ich eine Reihe von Zeichen in der Datei durch den Namen der Datei ersetzen. Zum Beispiel:

Derzeit in allen Dateien:

datafname = example.nex
ofprefix = best.example

Ideale Ausgabe:

Dateiname: 25.conf

datafname = 25.nex
ofprefix = best.25

Dateiname: 26.conf

datafname = 26.nex
ofprefix = best.26

Ich dachte, ich könnte sedall diese Dateien durchgehen, um die Textzeichenfolge zu finden und durch den Dateinamen zu ersetzen.

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

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

Antworten:


9

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 -iSchalter auf verwenden sed, müssen Sie absolut sicher sein, dass Ihr sedBefehl funktioniert, da -idie Dateien an Ort und Stelle geändert werden . 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 verwendet, -i.beforedie eine *.beforeDatei mit dem ursprünglichen Inhalt hinterlassen wird .


Ja, dies ist 100% zum Thema @foolsparadise. PerlDuck, bitte machen Sie sich mit dem Umfang der Website vertraut, bevor Sie etwas anderes vorschlagen.
Terdon

5

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, da sonst die Variable nicht erweitert wird.

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

2

Mit GNU können Sie die Aufgabe ohne Schleife ausführen parallel Parallel installieren:

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

Dies ist besonders nützlich, wenn Sie viele Dateien bearbeiten müssen, da parallelein Job pro CPU-Kern ausgeführt wird.

  • -i.oldbedeutet: Bearbeiten Sie die Datei in-place und erstellen Sie eine Sicherungskopie, indem Sie die .oldErweiterung zum ursprünglichen Dateinamen hinzufügen (entfernen .oldSie diese , wenn Sie keine Sicherungskopie wünschen, aber denken Sie daran, dass Sie dann keine Sicherungskopie haben).
  • s/example/{.}/gbedeutet substitute examplemit dem eingegebenen Dateinamen ohne seine Erweiterung ( {.}) und mache es global (= bei jedem Auftreten)
  • {} wird durch den Eingabedateinamen ersetzt
  • ::: trennt den auszuführenden Befehl von den Argumenten, die an ihn übergeben werden sollen
  • *.confstimmt mit jeder .confDatei im aktuellen Verzeichnis überein

@OleTange Sie haben wahrscheinlich Recht, ich bin mir nicht ganz sicher über die richtige Terminologie und habe gerade die Funktion wie man paralleljetzt beschrieben. Vielen Dank!
Nachtisch

Elegante Lösung. Anfangs habe ich mir Sorgen gemacht, ob es kaputt gehen würde, wenn die Dateinamen Leerzeichen enthalten, aber Sie haben das auch abgedeckt.
Ole Tange

@OleTange I? Nein, parallelabgedeckt! Es ist einfach eine erstaunliche Software, wenn Sie mich fragen, die als Ersatz für fast jede forSchleife und jeden xargsAnruf nützlich ist .
Dessert

@OleTange Oh warte, ich habe gerade gemerkt, dass du das vielleicht schon gewusst hast. : D Vielen Dank, dass Sie es so einfach gemacht haben --will-cite!
Dessert

1

Mit awk, bei dem eine FILENAMEVariable automatisch auf den Dateinamen gesetzt wird (und, wenn 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 auf und speichern Sie ihn im fileArray
  • {gsub("example", file[1])} 1: Ersetzen Sie für alle Zeilen durch exampledas erste Element des fileArrays und drucken Sie.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.