Bash - Manipulation de chaîne continue

11
#!/bin/bash

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

Existe-t-il de toute façon de coller ces deux lignes ensemble dans une doublure?

gsklee
la source

Réponses:

12

FILE=$(basename "${1/%.jpeg/.jpg}") travaillé pour moi.

tester:

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

contenu du script:

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

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

echo "$FILE"
Tim Kennedy
la source
Étant donné que les deux lignes sont un peu interchangeables, cette solution est jusqu'à présent la plus soignée ... Si les lignes ne sont pas interchangeables, sedelles seront définitivement nécessaires, je suppose.
gsklee
11

Vous ne pouvez pas imbriquer d'extensions dans bash (ni dans ksh, ash et autres coquilles en dehors de zsh). Il ne s'agit que d'une limitation esthétique, car, comme vous l'illustrez, vous pouvez affecter une expression intermédiaire à une variable temporaire. C'est un peu ennuyeux pour les monolignes, mais dans les scripts, c'est sans doute meilleur pour la lisibilité.

Vous pouvez éviter d'utiliser l'utilitaire externe basenameet utiliser une construction de manipulation de chaîne à la place:

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

Ici, il arrive que vous puissiez réécrire votre script pour mettre la substitution de commandes à l'extérieur . Ce n'est pas un phénomène général, et vous ne gagnez rien d'autre qu'un certain sentiment de doublure.

Zsh, pour le meilleur ou pour le pire, vous permet d'imbriquer des extensions:

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

Ou vous pouvez utiliser la construction intégrée de zsh au lieu de basename:

FILE=${${1:t}/%.jpeg/.jpg}
Gilles 'SO- arrête d'être méchant'
la source
4

J'irais pour:

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

Le deuxième paramètre de basename est un suffixe à supprimer du nom de fichier (voir man basename)

Chirlo
la source
3

Vous pouvez utiliser une seule sedcommande comme dans l'exemple suivant:

FILE=$(sed 's/.*\///;s/\.jpeg$/.jpg/' <<<"$1")
enzotib
la source
2

L'intégration sed, cela devrait faire l'affaire:

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

(Cela ne répond pas exactement à votre question parce que je ne peux pas; je ne sais pas si c'est possible.)

sr_
la source
1

Les ${}constructions Bash fonctionnent avec des noms de variables , il n'y a donc aucun moyen d'incorporer une commande directement. L'approche de @ sr_ est une alternative si cela ne vous dérange pas le fork supplémentaire.

l0b0
la source
1

La ligne

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

peut être raccourci et rendu plus portable avec

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