Wie kann man mehr als einen Teilstring gleichzeitig in Bash ersetzen?

Ich habe ein Verzeichnis mit Bilddateien, die in Bash wiedergegeben werden sollen. Während des Echos möchte ich sowohl den Dateinamen als auch die Erweiterung in einem einzeiligen Befehl ersetzen.

Beispieldateien:

images/file_name_1.jpg images/file_name_2.jpg 

Normalerweise kann ich eine einzelne Ersetzung wie folgt durchführen:

 for i in images/*; do echo ${i/file/image}; done  

Und die Ausgabe lautet wie folgt:

 images/image_name_1.jpg images/image_name_2.jpg  

Wie kann ich die for-Schleife beibehalten und die Zeichenfolge „jpg“ auch durch „png“ ersetzen? Es ist nur eine Instanz, ich könnte den Punkt durch Komma usw. ersetzen.

Wenn ich dies versuche:

 for i in images/*; do echo ${{i/jpg/png}/file/image}; done  

Es funktioniert nicht. Ich konnte keine andere Lösung oder Idee finden. Ist dies möglich, wenn ja, wie?

Kommentare

  • Ich ' Ich weiß nicht, warum dies ' in bash nicht funktioniert hat, aber verschachtelte Ersetzungen funktionieren genau so, wie Sie es in zsh erwartet haben bessere Shell;)

Antwort

Der einfache Ansatz wäre, das Ergebnis einer Variablen zuzuweisen und dann zu arbeiten Beispiel:

 for filename in images/* do echo "filename is now $filename" filename=${filename/jpg/png}; echo "filename is now $filename" filename=${filename/file/image}; echo "filename is now $filename" echo "final filename is ${filename}" done  

Kommentare

  • Diese Antwort ist nicht vollständig. Die Ersetzungen gelten an einer beliebigen Stelle in den Dateinamenzeichenfolgen. Basierend auf der Frage möchte Kubilay ein Präfix und eine Erweiterung (Suffix) ersetzen. Können Sie dies ändern und berücksichtigen? : $ {var / # Pattern / Replacement} Wenn das Präfix von var mit Pattern übereinstimmt, ersetzen Sie Pattern durch Replacement. $ {var /% Pattern / Replacement} If Das Suffix var stimmt mit Pattern überein und ersetzt Pattern durch Ersetzen.
  • @rMistero ' gibt es keine Regel gegen das Posten einer anderen Antwort, nur weil eine Antwort akzeptiert wurde. Tatsächlich denke ich, dass Sie dies tun sollten, zumal die Semantik Ihrer Vorschläge unterschiedlich ist. Dies ist jedoch der Weg, um das zu tun, was das OP versucht hat. Selbst wenn es andere Ergebnisse gibt, die ebenfalls gültig sein könnten, kann man davon ausgehen, dass dies mit dem übereinstimmt, was das OP erreichen wollte / li>

Antwort

Sie können die vorherige Ersetzung einer Variablen zuweisen und stattdessen Ersetzen für diese Variable ausführen

 for i in images/* do j=${i/jpg/png} echo ${j/file/image} done  

Kommentare

  • Nicht sicher ob es funktioniert. " für i in images / *; do j = {i / jpg / png} echo $ {j / file / image}; " wiederholt " {i / jpg / png} " wiederholt.
  • Jetzt ja: " für i in images / *. Jpg; do j = $ {i / jpg / png}; echo $ {j / file / image}; erledigt ". Vielen Dank!

Antwort

, um eine beliebige Zeichenfolge zu ändern:

$ echo "images/file_name_1.jpg" | perl -pE "s/file/image/;s/jpg$/png/;" images/image_name_1.png 

eine Verknüpfung zum Umbenennen (was das ultimative Ziel sein kann:

$ rename "s/file/image/;s/jpg$/png/;" "$i" 

Kommentare

  • Ich denke immer noch, dass es übertrieben ist, Perl einmal für jede Datei aufzurufen, aber zumindest gibt dies jetzt eine Antwort auf die Frage. 🙂
  • @MichaelKj ö rling Sie müssen ' nicht für jede Datei Perl aufrufen, sondern können rename … images/* ausführen. Dies erfordert jedoch eine Debian-basierte Distribution (rename unter anderen Linux-Varianten ist ein völlig anderer Befehl).
  • @Gilles Ich habe mehr über die erste Version nachgedacht. zumal ' nichts in der Frage zum Umbenennen von Dateien steht. Die ursprüngliche (Nachfrist bearbeitete) Version dieser Antwort enthielt nur den Befehlsvorschlag rename.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.