Bash - Kontinuierliche String-Manipulation

11
#!/bin/bash

FILE="$(basename "$1")"
FILE="${FILE/%.jpeg/.jpg}"

Gibt es überhaupt eine Möglichkeit, diese beiden Linien zu einem Einzeiler zusammenzukleben?

gsklee
quelle

Antworten:

12

FILE=$(basename "${1/%.jpeg/.jpg}") arbeitete für mich.

Prüfung:

bash-$ ./test.sh /tmp/foo.jpeg
foo.jpg

Skriptinhalt:

bash-$ cat test.sh 
#!/usr/bin/bash

FILE=$(basename "${1/%.jpeg/.jpg}")

echo "$FILE"
Tim Kennedy
quelle
Da die beiden Leitungen irgendwie austauschbar sind, ist diese Lösung bisher die sauberste ... Wenn die Leitungen nicht austauschbar sind, sedwird sie definitiv benötigt, denke ich.
Gsklee
11

Sie können Erweiterungen nicht in Bash (oder in Ksh, Asche und anderen Muscheln außer Zsh) verschachteln. Dies ist nur eine kosmetische Einschränkung, da Sie, wie Sie veranschaulichen, einer temporären Variablen einen Zwischenausdruck zuweisen können. Es ist ein wenig nervig für Einzeiler, aber in Skripten ist es wohl besser für die Lesbarkeit.

Sie können die Verwendung des externen Dienstprogramms vermeiden basenameund stattdessen ein Konstrukt zur Manipulation von Zeichenfolgen verwenden:

FILE="${1##*/}"; FILE="${FILE/%.jpeg/.jpg}"

Hier kann es vorkommen, dass Sie Ihr Skript neu schreiben können, um die Befehlsersetzung nach außen zu verschieben . Das ist kein allgemeines Phänomen, und Sie gewinnen auch nichts anderes als ein bestimmtes Einzeiler-Gefühl.

Zsh, zum Guten oder zum Schlechten, lässt Sie Erweiterungen verschachteln:

FILE=${$(basename $1)/%.jpeg/.jpg}    # using basename
FILE=${${1##*/}/%.jpeg/.jpg}          # using string rewriting

Oder Sie können das integrierte Konstrukt von zsh anstelle von basename:

FILE=${${1:t}/%.jpeg/.jpg}
Gilles 'SO - hör auf böse zu sein'
quelle
4

Ich würde gehen für:

FILE=$(basename $1 .jpeg).jpg

Der zweite Parameter für den Basisnamen ist ein Suffix, das aus dem Dateinamen entfernt werden soll (siehe man basename).

Chirlo
quelle
3

Sie können einen einzelnen sedBefehl wie folgt verwenden:

FILE=$(sed 's/.*\///;s/\.jpeg$/.jpg/' <<<"$1")
Enzotib
quelle
2

Die Einbeziehung sedsollte dieser den Trick:

FILE="$(basename "$1" | sed s/\.jpeg$/.jpg/)"

(Dies beantwortet Ihre Frage nicht genau, weil ich es nicht kann. Ich bin mir nicht sicher, ob es möglich ist.)

sr_
quelle
1

Die Bash- ${}Konstrukte arbeiten mit Variablennamen , sodass ein Befehl nicht direkt eingebettet werden kann. Der Ansatz von @ sr_ ist eine Alternative, wenn Ihnen die zusätzliche Gabel nichts ausmacht.

l0b0
quelle
1

Die Linie

FILE=$(basename "${1/%.jpeg/.jpg}")

kann gekürzt und tragbarer gemacht werden mit

FILE=$(basename "${1%.jpeg}.jpg")
Peter John Acklam
quelle