Concatenare due variabili con un carattere di sottolineatura


55

Devo concatenare due variabili per creare un nome file con un carattere di sottolineatura. Consente di chiamare le mie variabili $FILENAMEe $EXTENSIONdove viene letto il nome file da un file.

FILENAME=Hello
EXTENSION=WORLD.txt

Adesso...

Ho provato quanto segue senza successo:

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

Ottengo sempre una sorta di output strano. Di solito il trattino basso prima.

Ne ho bisogno

echo $NAME
Hello_WORLD.txt

2
Probabilmente la tua sceneggiatura contiene caratteri di ritorno a capo.
Stéphane Chazelas,

Sì, era quello. : D
Rhyuk,

Risposte:


68

Puoi usare qualcosa del genere:

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

Funziona anche così:

NAME=${FILENAME}_${EXTENSION}

1
Il problema era il file da cui stavo leggendo NAME. Formattazione di Windows ... La tua soluzione ha funzionato alla grande dopo. Grazie
Rhyuk,

2
Il primo comando altera il valore della variabile e l'uso di una sostituzione di comando e echonon può essere di aiuto. Il secondo comando era già stato dato nella domanda.
Gilles 'SO- smetti di essere malvagio' il

1
Sì! Lo adoro. Questo mi ha infastidito per molto tempo. Grazie per la soluzione!
racl101,

Questo funziona per me. Quando utilizzo "$ FILENAME_ $ EXTENSION", vengono visualizzati solo i valori di "$ EXTENSION". Potresti per favore aiutare a spiegare perché questo accade? Grazie
Lei Hao, il

12

Il tuo:

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

vanno tutti bene, quindi sarebbe:

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

(ma certamente non NAME=$(echo ${FILENAME}_${EXTENSION}) come usaecho e l' split+globoperatore ).

NAME=$FILENAME_$EXTENSION

sarebbe stato lo stesso di:

NAME=${FILENAME_}${EXTENSION}

poiché _(contrariamente a \o ') è un carattere valido in un nome di variabile.

Il tuo problema è che avevi delle linee delimitate con CRLF invece che solo LF, il che significava che quel contenuto variabile terminava in carattere CR.

Il carattere CR, quando scritto su un terminale, dice al terminale di spostare il cursore all'inizio della riga. Quindi, Hello<CR>_WORLD.TXT<CR>quando inviato a un terminale mostrerebbe come _WORLD.TXT(sovrascrivendo il Hello).


1

Sono passato all'utilizzo della ${FILENAME}_${EXTENSION}sintassi sopra menzionata.

Ho usato per usare $()quando avevo bisogno di concatenare due variabili con un carattere di sottolineatura. Ad esempio, $YYYYMMDD$()_$HHMMSSper generare un nome file contenente un timestamp nel formato AAAAMMGG_HHMMSS. Il centro $()non restituisce nulla e separa le due variabili.

Ho usato timeper misurare i compiti usando il $YYYYMMDD$()_$HHMMSSmetodo e alcuni di quelli sopra, e tutti hanno riportato 0ms sul vecchio server su cui sto usando questo. Le prestazioni non sembrano essere un problema.


Questo non risponde alla domanda. Dovresti fare una nuova domanda per questo. $()fa un fork di una subshell in poche shell (alcune le ottimizzano via). Dirotta anche un operatore per qualcosa per cui non è stato progettato. ${x}_yè quello che vuoi.
Stéphane Chazelas,

Cosa intendi con "Questo non risponde alla domanda"? Non è una risposta eccezionale, ma è una risposta.
Scott,

Modificato per rimuovere l'ambiguità.
user208145

0

Dovresti usare le variabili in minuscolo (è la migliore pratica).
Quindi, userò il nome del file e l'estensione invece di FILENAME ed EXTENSION

Come dici che "il nome del file viene letto da un file", suppongo che lo script sia:

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

E che si desidera concatenare entrambe le variabili $ nomefile e $ estensione con un trattino basso _.
Gli esempi forniti (tranne: no double \) funzionano correttamente qui:

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

Come alcuni altri:

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

Quindi, il tuo problema non è con il modo in cui le variabili si uniscono, ma con il contenuto delle variabili. Sembra ragionevole pensare che questo:

read -r filename  <file.txt

leggerà un ritorno a capo finale \rse si legge da un file di Windows.

Una soluzione semplice (per ksh, bash, zsh) è rimuovere tutti i caratteri di controllo dalla variabile di lettura:

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

Questo potrebbe essere simulato con un valore che ha un ritorno a capo:

$ 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

Oppure, sostituendo il valore di filename:

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

Conclusione.

Così questo:

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

Otterrà il valore corretto nameanche se gli altri var contengono caratteri di controllo.



-2

Puoi anche usarlo: separa i var separati con spazi e concatenali usando tr per rimuovere lo spazio.

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) A questa domanda è già stata data una risposta più che adeguata. (2) Cosa fa la tua risposta se la variabile esistente contiene caratteri speciali?
G-Man dice "Ripristina Monica" il

Questo non risolve il problema con la variabile che contiene un ritorno a capo. Rimuove anche gli spazi, qualcosa che potrebbe non essere desiderato.
Kusalananda

@Kusalananda: In realtà, a meno che non stia trascurando qualcosa, questo gestisce il ritorno della carrozza bene; gli spazi sono l'unico problema.
G-Man dice "Ripristina Monica" il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.