Concaténer deux variables avec un trait de soulignement

55

Je dois concaténer deux variables pour créer un nom de fichier comportant un trait de soulignement. Permet d'appeler mes variables $FILENAMEet $EXTENSIONoù le nom de fichier est lu à partir d'un fichier.

FILENAME=Hello
EXTENSION=WORLD.txt

Maintenant...

J'ai essayé ce qui suit sans succès:

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

Je reçois toujours une sorte de sortie étrange. Habituellement, le soulignement en premier.

J'ai besoin que ça soit

echo $NAME
Hello_WORLD.txt
Rhyuk
la source
2
Votre script contient probablement des caractères de retour chariot.
Stéphane Chazelas
Oui ça y était. : D
Rhyuk

Réponses:

68

Vous pouvez utiliser quelque chose comme ceci:

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

Cela fonctionne aussi bien:

NAME=${FILENAME}_${EXTENSION}
Tim
la source
1
Le problème était le fichier dans lequel je lisais les NOMS. Le formatage Windows ... Votre solution a bien fonctionné par la suite. Merci
Rhyuk
2
La première commande modifie la valeur de la variable et l'utilisation d'une substitution de commande et echone peut éventuellement pas aider. La deuxième commande était déjà donnée dans la question.
Gilles, arrête de faire le mal
1
Oui! J'aime cela. Cela me fâchait le plus longtemps possible. Merci pour la solution!
racl101
Cela fonctionne pour moi. Lorsque j'utilise '$ FILENAME_ $ EXTENSION', seules les valeurs de '$ EXTENSION' apparaissent. Pourriez-vous s'il vous plaît aider à expliquer pourquoi cela se produit? Merci
Lei Hao
12

Votre:

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

sont tous bien, alors serait:

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

(mais certainement pas NAME=$(echo ${FILENAME}_${EXTENSION}) comme il utiliseecho et l' split+globopérateur ).

NAME=$FILENAME_$EXTENSION

aurait été la même chose que:

NAME=${FILENAME_}${EXTENSION}

comme _(contrairement à \ou ') est un caractère valide dans un nom de variable.

Votre problème est que vous aviez des lignes délimitées par CRLF au lieu de simplement LF, ce qui signifie que ces contenus variables se terminaient par un caractère CR.

Le caractère CR, lorsqu'il est écrit sur un terminal, indique au terminal de déplacer le curseur au début de la ligne. Ainsi, Hello<CR>_WORLD.TXT<CR>lorsqu’il est envoyé à un terminal s’affiche _WORLD.TXT(en remplaçant le Hello).

Stéphane Chazelas
la source
1

Je suis passé à utiliser la ${FILENAME}_${EXTENSION}syntaxe mentionnée ci-dessus.

J'avais l'habitude d'utiliser $()quand j'avais besoin de concaténer deux variables avec un trait de soulignement. Par exemple, $YYYYMMDD$()_$HHMMSSpour générer un nom de fichier contenant un horodatage au format AAAAMMJJHHMMSS. Le milieu $()ne renvoie rien et sépare les deux variables.

J'ai l'habitude timede mesurer les assignations à l'aide de la $YYYYMMDD$()_$HHMMSSméthode et de certaines des méthodes ci-dessus, et ils ont tous signalé 0 ms sur l'ancien serveur sur lequel je l'utilise. La performance ne semble pas être un problème.

utilisateur208145
la source
Cela ne répond pas à la question. Vous devriez poser une nouvelle question à ce sujet. $()fourche un sous-shell dans quelques coquillages (certains l’optimisent au loin). C'est également détourner un opérateur pour quelque chose pour lequel il n'a pas été conçu. ${x}_yc'est ce que tu veux.
Stéphane Chazelas
Que voulez-vous dire par "Cela ne répond pas à la question"? Ce n'est pas une bonne réponse, mais c'est une réponse.
Scott
Édité pour lever l'ambiguïté.
user208145
0

Vous devez utiliser des variables en minuscule (c'est la meilleure pratique).
Donc, je vais utiliser le nom de fichier et l'extension au lieu de FILENAME et EXTENSION

Comme vous dites que "nom de fichier est lu à partir d'un fichier", je suppose que le script est:

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

Et que vous souhaitiez concaténer les variables $ filename et $ extension avec un trait de soulignement _.
Les exemples que vous fournissez (sauf: pas de double \) fonctionnent correctement ici:

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

Comme un autre:

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

Votre problème ne réside donc pas dans la façon dont les variables sont collées ensemble, mais dans le contenu des variables. Il semble raisonnable de penser que ceci:

read -r filename  <file.txt

lira un retour chariot final \rs'il lit un fichier Windows.

Une solution simple (pour ksh, bash, zsh) consiste à supprimer tous les caractères de contrôle de la variable en lecture:

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

Cela pourrait être simulé avec une valeur qui a un retour chariot:

$ 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, en remplaçant la valeur de filename:

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

Conclusion.

Donc ça:

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

Obtiendra la valeur correcte namemême si les autres vars contiennent des caractères de contrôle.


la source
-2

Vous pouvez également utiliser ceci: séparez les vars séparés par des espaces et concaténez-les à l'aide de tr pour supprimer l'espace.

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
la source
(1) Cette question a déjà fait l’objet d’une réponse plus que satisfaisante. (2) Que fait votre réponse si la variable existante contient des caractères spéciaux?
G-Man dit 'Réintégrez Monica'
Cela ne résout pas le problème de la variable contenant un retour à la ligne. Il supprime également les espaces, ce qui peut ne pas être souhaité.
Kusalananda
@ Kusalananda: En fait, à moins que je ne néglige quelque chose, le retour des chariots est parfait; les espaces sont le seul problème.
G-Man dit 'Réintégrez Monica'