Bir glob paterninden tanımlanan değişken ile bas değiştirme


10

Aşağıdaki örnek sorunu açıklamaktadır. Neden olduğunu FILENAMEyankılandı ve ikame kullanırken bir desen olarak algılanan zaman doğru basılmış?

#!/bin/bash

FILEPATH_WITH_GLOB="/home/user/file_*"
FILENAME=$(basename "$FILEPATH_WITH_GLOB")
echo $FILENAME                #file_1234
echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

Yanıtlar:


15
FILEPATH_WITH_GLOB="/home/user/file_*"

Şimdi FILEPATH_WITH_GLOBiçeriyor/home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAMEiçerir file_*.

echo $FILENAME                #file_1234

$FILENAMEliste bağlamında alıntı yapılmadığında, bu genişletme split + glob işlecinden geçer, bu da eşleşen dosya listesine genişletilir: parametre genişletmesi üzerine dosya adı üretimi gerçekleştirilir .

echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

Hala liste bağlamında alıntılanmamış bir parametre genişletmesi, bu yüzden hala split + glob geçiriyor. Bununla birlikte, burada ile_*desen herhangi bir dosyayla eşleşmez, bunun yerine kendi kendine genişler.

Muhtemelen burada istediğiniz şey:

shopt -s nullglob # have globs expand to nothing when they don't match
set -- /home/user/file_* # expand that pattern into the list of matching 
                         # files in $1, $2...
for file do  # loop over them
  filename=$(basename -- "$file")
  printf '%s\n' "$filename" "${filename:1:5}"
done

Veya bunları bir dizide saklayabilirsiniz:

shopt -s nullglob
files=(/home/user/file_*)

Yalnızca ilk eşleşmeyi önemsiyorsanız veya yalnızca bir eşleşme olduğunu biliyorsanız, bu dosyaya şu adresten başvurabilirsiniz $files. bashgenellikle can sıkıcı davranışa sahip olduğu $filesiçin genişlediğinde ${files[0]}yerine tüm (miras bir davranış dizinin elemanlarının kshsabit, zshbir kez olsun istedik davranış olur), ama burada.


Açıklama için teşekkürler. FILEPATH_WITH_GLOB=`echo /home/user/file_*` Açıklamanızdan sonra geçici bir çözüm yapmayı başardınız.
TheMeaningfulEngineer

@Alan, buna hitap etmenin yanlış yolu bu. Burada bir dizi kullanmak istiyorsunuz. Ya örneğimdeki gibi ($ 1, $ 2 ...) konumsal parametreler ya da bash: gibi bir dizi files=(/home/user/file_*).
Stéphane Chazelas

(ve tüm büyük harfli değişkenler gerçekten ortam değişkenleri için echoayrılmalıdır, rasgele veriler için kullanılmamalıdır , değişkenler liste bağlamında tırnaksız bırakılmamalıdır).
Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.