Об’єднання двох змінних із підкресленням


54

Мені потрібно об'єднати дві змінні, щоб створити ім'я файлу, що має підкреслення. Назвемо мої змінні $FILENAMEі $EXTENSIONде ім'я файлу зчитується з файлу.

FILENAME=Hello
EXTENSION=WORLD.txt

Тепер ...

Я безрезультатно намагався:

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

Я завжди отримую якийсь дивний вихід. Зазвичай підкреслюється спочатку.

Мені це потрібно

echo $NAME
Hello_WORLD.txt

2
Можливо, ваш сценарій містить символи повернення каретки.
Стефан Шазелас

Так, це було все. : D
Рюк

Відповіді:


67

Ви можете використовувати щось подібне:

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

Це також працює:

NAME=${FILENAME}_${EXTENSION}

1
Проблемою був файл, з якого я читав імена NAME. Форматування Windows ... Ваше рішення працювало чудово після цього. Спасибі
Рюк

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}

оскільки _(всупереч \або ') є дійсним символом в імені змінної.

Ваша проблема полягає в тому, що у вас були рядки, обмежені CRLF, а не лише LF, що означало, що цей змінний вміст закінчується символом CR.

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


1

Я перейшов на використання ${FILENAME}_${EXTENSION}синтаксису, згаданого вище.

Я використовував, $()коли мені потрібно було об'єднати дві змінні з підкресленням. Наприклад, $YYYYMMDD$()_$HHMMSSдля створення імені файлу, що містить часову позначку у форматі YYYYMMDD_HHMMSS. Середина $()нічого не повертає і розбиває дві змінні.

Раніше я timeвимірював завдання за допомогою $YYYYMMDD$()_$HHMMSSметоду та деяких із наведених вище, і всі вони повідомляли 0ms на старому сервері, на якому я це використовую. Продуктивність, здається, не є проблемою.


Це не відповідає на запитання. Ви повинні поставити нове питання для цього. $()робить розщеплення нижньої оболонки в декількох оболонках (деякі оптимізують її). Це також викрадення оператора на те, на що він не був розроблений. ${x}_yце те, що ти хочеш.
Стефан Шазелас

Що ви маєте на увазі: «Це не відповідає на питання». Це не велика відповідь, але це відповідь.
Скотт

Відредаговано, щоб усунути неоднозначність.
користувач208145

0

Ви повинні використовувати змінні в малі регістри (це найкраща практика).
Отже, я використовуватиму ім’я файлу та розширення замість 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навіть якщо інші параметри містять контрольні символи.



-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"

(1) На це питання вже відповіли більш ніж достатньо. (2) Що робить ваша відповідь, якщо існуюча змінна має в ній спеціальні символи?
G-Man каже: "Відновіть Моніку"

Це не вирішує проблему зі змінною, що містить повернення каретки. Це також видаляє пробіли, те, що може бути непотрібним.
Kusalananda

@Kusalananda: Насправді, якщо я щось не помічаю, ця обробка каретки повертається просто чудово; простори - єдина проблема.
G-Man каже: "Відновіть Моніку"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.