Объединение двух переменных с подчеркиванием

55

Мне нужно объединить две переменные, чтобы создать имя файла с подчеркиванием. Позволяет вызвать мои переменные $FILENAMEи $EXTENSIONгде имя файла читается из файла.

FILENAME=Hello
EXTENSION=WORLD.txt

В настоящее время...

Я попробовал следующее без успеха:

NAME=${FILENAME}_$EXTENSION
NAME=${FILENAME}'_'$EXTENSION
NAME=$FILENAME\\_$EXTENSION

Я всегда получаю какой-то странный вывод. Обычно подчеркивание первое.

Мне нужно чтобы это было

echo $NAME
Hello_WORLD.txt
Rhyuk
источник
2
Возможно, ваш скрипт содержит символы возврата каретки.
Стефан Шазелас
Да, это было это. : D
Rhyuk

Ответы:

68

Вы можете использовать что-то вроде этого:

NAME=$(echo ${FILENAME}_${EXTENSION})

Это работает также:

NAME=${FILENAME}_${EXTENSION}
Тим
источник
1
Проблема была в файле, откуда я читал Имена. Форматирование Windows ... Ваше решение прекрасно сработало после этого. Спасибо
Rhyuk
2
Первая команда изменяет значение переменной и использование подстановки команд и echoне может помочь. Вторая команда уже была дана в вопросе.
Жиль "ТАК - перестань быть злым"
1
Да! Я люблю это. Это чертовски раздражало меня долгое время. Спасибо за решение!
racl101
Это работает для меня. Когда я использую '$ FILENAME_ $ EXTENSION', отображаются только значения '$ EXTENSION'. Не могли бы вы помочь объяснить, почему это происходит? Спасибо
Лэй Хао
12

Твой:

NAME=${FILENAME}_$EXTENSION
NAME=${FILENAME}'_'$EXTENSION

все в порядке, так будет:

NAME=${FILENAME}_${EXTENSION}
NAME=$FILENAME'_'$EXTENSION
NAME=$FILENAME\_$EXTENSION
NAME=$FILENAME"_$EXTENSION"

(но , конечно , не NAME=$(echo ${FILENAME}_${EXTENSION}) так он используетecho и оператор ).split+glob

NAME=$FILENAME_$EXTENSION

было бы так же, как:

NAME=${FILENAME_}${EXTENSION}

as _(вопреки \или ') является допустимым символом в имени переменной.

Ваша проблема в том, что у вас были строки, разделенные CRLF, а не просто LF, что означало, что содержимое этой переменной заканчивалось символом CR.

Символ CR при записи в терминал говорит терминалу переместить курсор в начало строки. Таким образом, Hello<CR>_WORLD.TXT<CR>при отправке в терминал будет отображаться как _WORLD.TXT(переопределение Hello).

Стефан Шазелас
источник
1

Я перешел на использование ${FILENAME}_${EXTENSION}синтаксиса, упомянутого выше.

Я использовал, $()когда мне нужно было объединить две переменные с подчеркиванием. Например, $YYYYMMDD$()_$HHMMSSчтобы сгенерировать имя файла, содержащее метку времени в формате ГГГГММДД_ЧЧММСС. Середина $()ничего не возвращает и разбивает две переменные.

Я использовал timeдля измерения назначений, используя $YYYYMMDD$()_$HHMMSSметод и некоторые из них выше, и все они сообщили 0 мс на старом сервере, на котором я использую это. Производительность не кажется проблемой.

user208145
источник
Это не отвечает на вопрос. Вы должны поднять новый вопрос для этого. $()разворачивает подоболочку в несколько оболочек (некоторые оптимизируют ее). Он также угоняет оператора за то, для чего он не предназначен. ${x}_yэто то, что вы хотите.
Стефан
Что вы имеете в виду, «Это не отвечает на вопрос»? Это не очень хороший ответ, но это ответ.
Скотт
Отредактировано для устранения двусмысленности.
user208145
0

Вы должны использовать переменные в нижнем регистре (это лучшая практика).
Итак, я буду использовать имя файла и расширение вместо 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Получит правильное значение, даже если другие переменные содержат управляющие символы.


источник
-2

Вы также можете использовать это: разделите отдельные переменные пробелами и объедините их, используя tr для удаления пробела.

TableNameToCreate="MyTable"
# concatenation work is done here 
$(echo "$TableNameToCreate _my_other_Info " | tr -d " ")

#Proof
echo "Var to create with var pasted as prefix to suffix
    $(echo "$TableNameToCreate _my_other_Info " | tr -d " ") 
. "

# create a new var
NewVar=$(echo "$TableNameToCreate _my_other_Info " | tr -d " ")

#proof
echo "$NewVar"
Greg
источник
(1) На этот вопрос уже был дан более чем адекватный ответ. (2) Что делает ваш ответ, если в существующей переменной есть специальные символы?
G-Man говорит: «Восстановите Монику»
Это не решает проблему с переменной, содержащей возврат каретки. Он также удаляет пробелы, то, что может быть нежелательным.
Кусалананда
@Kusalananda: На самом деле, если я не пропускаю что-то, это отлично справляется с возвратом каретки; пробелы - единственная проблема.
G-Man говорит: «Восстановите Монику»