Заміна баша зі змінною, визначеною з глобальної картини


10

Наведений нижче приклад пояснює проблему. Чому FILENAMEдрукується правильно, коли лунає і сприймається як зразок при використанні підстановки?

#!/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

Відповіді:


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

Тепер, FILEPATH_WITH_GLOBмістить/home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAMEмістить file_*.

echo $FILENAME                #file_1234

$FILENAMEне котируючись у контексті списку, це розширення зазнає оператора split + glob, тому він розширюється до списку відповідного файлу: генерація імені файлу виконується після розширення параметра .

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

Це все ще без котирування розширення параметрів у контексті списку, тому все ще зазнає розбиття + glob. Однак тут ile_*шаблон не відповідає жодному файлу, тому він замість нього розширюється.

Можливо, ви тут хочете:

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

Або ви можете зберігати їх у масиві:

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

Якщо ви дбаєте лише про перший матч, або знаєте, що є лише одна відповідність, ви можете звернутися до цього файлу як $files. bashмає таку дратівливу поведінку, яка $filesрозширюється ${files[0]}замість усіх елементів масиву (поведінка, успадкована від ksh, зафіксована zsh), але тут це було б бажаною поведінкою на один раз.


Дякую за пояснення. FILEPATH_WITH_GLOB=`echo /home/user/file_*` Після вашого пояснення вдалося вирішити проблему .
TheMeaningfulEngineer

@Alan, це неправильний спосіб вирішити це. Тут ви хочете використовувати масив. Або позиційні параметри , як в моєму прикладі ($ 1, $ 2 ...) або bashмасив , як: files=(/home/user/file_*).
Стефан Шазелас

(і всі великі регістри дійсно повинні бути зарезервовані для змінних середовища, echoне повинні використовуватися для довільних даних ; змінні не повинні залишатися без котирування у контекстах списку).
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.