Concatenando duas variáveis ​​com um sublinhado

54

Preciso concatenar duas variáveis ​​para criar um nome de arquivo que tenha um sublinhado. Vamos chamar minhas variáveis $FILENAMEe $EXTENSIONonde o nome do arquivo é lido de um arquivo.

FILENAME=Hello
EXTENSION=WORLD.txt

Agora...

Eu tentei o seguinte sem sucesso:

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

Eu sempre recebo algum tipo de saída estranha. Normalmente, o sublinhado primeiro.

Eu preciso que seja

echo $NAME
Hello_WORLD.txt
Rhyuk
fonte
2
Provavelmente, seu script contém caracteres de retorno de carro.
Stéphane Chazelas
Sim foi isso. : D
Rhyuk 27/08

Respostas:

67

Você pode usar algo como isto:

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

Isso também funciona:

NAME=${FILENAME}_${EXTENSION}
Tim
fonte
11
O problema era o arquivo de onde eu estava lendo os NAMEs. Formatação do Windows ... Sua solução funcionou muito bem depois disso. Graças
Rhyuk
2
O primeiro comando gerencia o valor da variável e o uso de uma substituição de comando e echonão pode ajudar. O segundo comando já foi dado na pergunta.
Gilles 'SO- stop be evil'
11
Sim! Eu amo isso. Isso estava me irritando por mais tempo. Obrigado pela solução!
racl101
Isso funciona para mim. Quando uso '$ FILENAME_ $ EXTENSION', apenas valores de '$ EXTENSION' são exibidos. Você poderia ajudar a explicar por que isso acontece? Obrigado
Lei Hao
12

Seu:

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

estão bem, então seria:

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

(mas certamente não NAME=$(echo ${FILENAME}_${EXTENSION}) como ele usaecho e o split+globoperador ).

NAME=$FILENAME_$EXTENSION

teria sido o mesmo que:

NAME=${FILENAME_}${EXTENSION}

como _(contrário a \ou ') é um caractere válido em um nome de variável.

Seu problema é que você tinha linhas delimitadas com CRLF em vez de apenas LF, o que significava que esse conteúdo variável terminava em caracteres CR.

O caractere CR, quando gravado em um terminal, informa ao terminal para mover o cursor para o início da linha. Portanto, Hello<CR>_WORLD.TXT<CR>quando enviado para um terminal, seria exibido como _WORLD.TXT(substituindo o Hello).

Stéphane Chazelas
fonte
1

Eu mudei para usar a ${FILENAME}_${EXTENSION}sintaxe mencionada acima.

Eu costumava usar $()quando precisava concatenar duas variáveis ​​com um sublinhado. Por exemplo, $YYYYMMDD$()_$HHMMSSpara gerar um nome de arquivo contendo um registro de data e hora no formato AAAAMMDD_HHMMSS. O meio $()não retorna nada e divide as duas variáveis.

Eu costumava timemedir as atribuições usando o $YYYYMMDD$()_$HHMMSSmétodo e algumas das opções acima, e todas elas relataram 0ms no servidor antigo em que estou usando isso. O desempenho não parece ser um problema.

user208145
fonte
Isso não responde à pergunta. Você deve levantar uma nova pergunta para isso. $()bifurca um subshell em algumas conchas (alguns o otimizam). Também está seqüestrando um operador para algo para o qual não foi projetado. ${x}_yé o que você quer.
Stéphane Chazelas
O que você quer dizer com "Isso não responde à pergunta"? Não é uma ótima resposta, mas é uma resposta.
30717 Scott
Editado para remover a ambiguidade.
precisa saber é o seguinte
0

Você deve usar variáveis ​​em minúsculas (é a melhor prática).
Então, usarei o nome do arquivo e a extensão em vez do FILENAME e EXTENSION

Como você diz que "o nome do arquivo é lido de um arquivo", assumirei que o script é:

read -r filename  <file.txt
extension=World.txt

E que você deseja concatenar as variáveis ​​$ filename e $ extension com um sublinhado _.
Os exemplos que você fornece (exceto: no double \) funcionam corretamente aqui:

name=${filename}_$extension
name=${filename}'_'$extension
name=$filename\_$extension

Como alguns outros:

name="${filename}"'_'"${extension}"
name="$filename"'_'"$extension"
name="${filename}_${extension}"

Portanto, seu problema não é como as variáveis ​​são unidas, mas com o conteúdo dos vars. Parece razoável pensar que isso:

read -r filename  <file.txt

lerá um retorno de carro à direita \rse estiver lendo um arquivo do Windows.

Uma solução simples (para ksh, bash, zsh) é remover todos os caracteres de controle da variável de leitura:

filename=${filename//[[:cntrl:]]/}

Isso pode ser simulado com um valor que possui um retorno de carro:

$ 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

Ou, substituindo o valor de filename:

$ filename="${filename//[[:cntrl:]]/}"
$ echo "start<$filename>end"
start<Hello>end

Conclusão.

Então, é isso:

name="${filename//[[:cntrl:]]/}_${extension//[[:cntrl:]]/}"

Obterá o valor correto para, namemesmo que os outros vars contenham caracteres de controle.


fonte
-2

Você também pode usar isso: separe os vars separados por espaços e concatene-os usando tr para remover o espaço.

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
fonte
(1) Esta pergunta já foi respondida mais do que adequadamente. (2) O que sua resposta faz se a variável existente tiver caracteres especiais?
G-Man diz 'Reinstate Monica'
Isso não resolve o problema com a variável que contém um retorno de carro. Também remove espaços, algo que pode não ser desejado.
Kusalananda
@Kusalananda: Na verdade, a menos que eu esteja negligenciando algo, isso lida com o retorno de carro muito bem; espaços são o único problema.
G-Man Diz 'Reinstate Monica' em