Ви повинні використовувати змінні в малі регістри (це найкраща практика).
Отже, я використовуватиму ім’я файлу та розширення замість FILENAME та EXTENSION
Як ви говорите, що "ім'я файлу читається з файлу", я вважаю, що сценарій:
read -r filename <file.txt
extension=World.txt
І що ви хочете об'єднати як змінні $ filename, так і $ extension з підкресленням _
.
Наведені вами приклади (крім: жодного подвійного \) тут не працюють правильно:
name=${filename}_$extension
name=${filename}'_'$extension
name=$filename\_$extension
Як і деякі інші:
name="${filename}"'_'"${extension}"
name="$filename"'_'"$extension"
name="${filename}_${extension}"
Отже, ваша проблема полягає не в тому, як змінні злипаються, а зі змістом vars. Здається розумним думати, що це:
read -r filename <file.txt
прочитає зворотний перевезення каретки, \r
якщо читає з файлу Windows.
Одне просте рішення (для ksh, bash, zsh) - видалити всі контрольні символи зі змінної читання:
filename=${filename//[[:cntrl:]]/}
Це може бути змодельовано значенням, яке має повернення каретки:
$ filename=$'Hello\r'
$ echo "starting<$filename>end"
>endting<Hello ### note the return to the start of line.
$ echo "starting<${filename//[[:cntrl:]]/}>end"
starting<Hello>end
Або замінюючи значення filename
:
$ filename="${filename//[[:cntrl:]]/}"
$ echo "start<$filename>end"
start<Hello>end
Висновок.
Отже це:
name="${filename//[[:cntrl:]]/}_${extension//[[:cntrl:]]/}"
Отримає правильне значення, name
навіть якщо інші параметри містять контрольні символи.