Вы должны использовать переменные в нижнем регистре (это лучшая практика).
Итак, я буду использовать имя файла и расширение вместо FILENAME и EXTENSION
Поскольку вы говорите, что «имя файла читается из файла», я предполагаю, что скрипт:
read -r filename <file.txt
extension=World.txt
И что вы хотите объединить обе переменные $ filename и $ extension с подчеркиванием _
.
Примеры, которые вы предоставляете (кроме: no double \), работают правильно:
name=${filename}_$extension
name=${filename}'_'$extension
name=$filename\_$extension
Как и некоторые другие:
name="${filename}"'_'"${extension}"
name="$filename"'_'"$extension"
name="${filename}_${extension}"
Итак, ваша проблема не в том, как переменные слипаются, а в содержимом переменных. Кажется разумным думать, что это:
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
Получит правильное значение, даже если другие переменные содержат управляющие символы.