Concatenando duas variáveis com um sublinhado

42

Eu preciso concatenar duas variáveis para criar um nome de arquivo que tenha um sublinhado. Vamos chamar minhas variáveis $FILENAME e $EXTENSION onde filename é 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. Geralmente o sublinhado primeiro.

Eu preciso que seja

echo $NAME
Hello_WORLD.txt
    
por Rhyuk 27.08.2013 / 22:06

6 respostas

57

Você pode usar algo assim:

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

Isso também funciona:

NAME=${FILENAME}_${EXTENSION}
    
por 27.08.2013 / 22:09
11

Seu:

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

estão todos 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 usa echo e o operador split+glob ).

NAME=$FILENAME_$EXTENSION

teria sido o mesmo que:

NAME=${FILENAME_}${EXTENSION}

como _ (ao contrário de \ 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 o conteúdo dessas variáveis terminava em caractere CR.

O caractere CR, quando escrito em um terminal, diz ao terminal para mover o cursor para o início da linha. Então Hello<CR>_WORLD.TXT<CR> quando enviado para um terminal seria mostrado como _WORLD.TXT (sobrescrevendo o Hello ).

    
por 08.01.2016 / 13:18
1

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

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

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

Então, o seu problema não está em como as variáveis estão juntas, mas com o conteúdo das vars. Parece razoável pensar que isso:

read -r filename  <file.txt

lerá um retorno de carro à direita \r se estiver lendo de 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 tenha 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:]]/}"

Obtém o valor correto para name , mesmo se as outras variantes contiverem caracteres de controle.

    
por 09.01.2016 / 02:42
1

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

Eu costumava usar $() quando eu precisava concatenar duas variáveis com um sublinhado. Por exemplo, $YYYYMMDD$()_$HHMMSS para 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 usei time para medir as atribuições usando o método $YYYYMMDD$()_$HHMMSS e algumas delas acima, e todas elas relataram 0ms no servidor antigo no qual estou usando. O desempenho não parece ser um problema.

    
por 25.11.2016 / 01:07
0

resposta de Stéphane Chazelas ,

NAME=${FILENAME}_$EXTENSION

é, evidentemente, a melhor resposta e deve ser a resposta aceita. Mas, no espírito da resposta do user208145 , aqui está uma alternativa:

UNDERSCORE='_'
NAME=$FILENAME$UNDERSCORE$EXTENSION
    
por 30.10.2017 / 20:27
-2

Você também pode usar isto: separe os vars separados com 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"
    
por 30.10.2017 / 17:23