Bash - Manipulasi String Berkelanjutan

11
#!/bin/bash

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

Apakah ada cara untuk merekatkan kedua garis ini menjadi satu garis?

gsklee
sumber

Jawaban:

12

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

uji:

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

isi skrip:

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

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

echo "$FILE"
Tim Kennedy
sumber
Karena dua baris agak saling dipertukarkan, solusi ini sejauh ini paling rapi ... Jika garis tidak dipertukarkan sedpasti akan diperlukan kurasa.
gsklee
11

Anda tidak dapat membuat sarang ekspansi di bash (atau di ksh, ash, dan shell lain selain dari zsh). Ini hanya batasan kosmetik, karena seperti yang Anda ilustrasikan, Anda dapat menetapkan ekspresi perantara ke variabel sementara. Agak menyebalkan untuk one-liners, tetapi dalam skrip lebih baik dibaca.

Anda bisa menghindari menggunakan utilitas eksternal basenamedan menggunakan konstruksi manipulasi string sebagai gantinya:

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

Di sini, itu terjadi bahwa Anda dapat menulis ulang skrip Anda untuk menempatkan substitusi perintah di luar . Itu bukan fenomena umum, Anda juga tidak mendapatkan apa pun selain perasaan satu garis tertentu.

Zsh, baik atau buruk, membuat Anda melakukan ekspansi sarang:

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

Atau Anda dapat menggunakan konstruksi bawaan zsh alih-alih basename:

FILE=${${1:t}/%.jpeg/.jpg}
Gilles 'SANGAT berhenti menjadi jahat'
sumber
4

Saya akan pergi untuk:

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

Parameter kedua untuk nama file adalah sufiks yang akan dihapus dari nama file (lihat man basename)

Chirlo
sumber
3

Anda bisa menggunakan satu sedperintah seperti berikut ini:

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

Dengan menggabungkan sed, ini harus melakukan trik:

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

(Ini tidak menjawab pertanyaan Anda karena saya tidak bisa; tidak yakin apakah itu mungkin.)

sr_
sumber
1

Bash ${}constructs bekerja dengan nama variabel , jadi tidak ada cara untuk menyematkan perintah secara langsung. Pendekatan @ sr_ adalah alternatif jika Anda tidak keberatan dengan garpu tambahan.

l0b0
sumber
1

Garis

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

dapat dipersingkat dan dibuat lebih portabel dengan

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