Verketten von zwei Variablen mit einem Unterstrich


54

Ich muss zwei Variablen verketten, um einen Dateinamen mit einem Unterstrich zu erstellen. Nennen wir meine Variablen $FILENAMEund $EXTENSIONwo Dateinamen aus einer Datei gelesen wird.

FILENAME=Hello
EXTENSION=WORLD.txt

Jetzt...

Ich habe folgendes erfolglos versucht:

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

Ich bekomme immer eine seltsame Ausgabe. In der Regel steht der Unterstrich an erster Stelle.

Ich muss es sein

echo $NAME
Hello_WORLD.txt

2
Wahrscheinlich enthält Ihr Skript Wagenrücklaufzeichen.
Stéphane Chazelas

Ja das war es. : D
Rhyuk

Antworten:


67

Sie können so etwas verwenden:

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

Das funktioniert auch:

NAME=${FILENAME}_${EXTENSION}

1
Das Problem war die Datei, aus der ich NAMEs gelesen habe. Windows-Formatierung ... Ihre Lösung hat danach hervorragend funktioniert. Vielen Dank
Rhyuk

2
Der erste Befehl verstümmelt den Wert der Variablen und die Verwendung einer Befehlsersetzung und echokann möglicherweise nicht helfen. Der zweite Befehl wurde bereits in der Frage gegeben.
Gilles 'SO - hör auf böse zu sein'

1
Ja! Ich liebe es. Das nervte mich am längsten. Danke für die Lösung!
racl101

Das funktioniert bei mir. Wenn ich '$ FILENAME_ $ EXTENSION' verwende, werden nur die Werte von '$ EXTENSION' angezeigt. Könnten Sie bitte erklären, warum dies passiert? Danke
Lei Hao

12

Ihre:

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

sind alle in Ordnung, so wäre:

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

(aber schon gar nicht so NAME=$(echo ${FILENAME}_${EXTENSION}) wie es gebrauchtecho und der split+globBetreiber ).

NAME=$FILENAME_$EXTENSION

wäre dasselbe gewesen wie:

NAME=${FILENAME_}${EXTENSION}

as _(im Gegensatz zu \oder ') ist ein gültiges Zeichen in einem Variablennamen.

Ihr Problem ist, dass Sie Zeilen hatten, die mit CRLF anstatt nur mit LF getrennt waren, was bedeutete, dass dieser variable Inhalt mit einem CR-Zeichen endete.

Das CR-Zeichen weist das Terminal beim Schreiben an, den Cursor an den Zeilenanfang zu bewegen. Also , Hello<CR>_WORLD.TXT<CR>wenn an ein Terminal gesendet würde zeigen , wie _WORLD.TXT(überschreibt die Hello).


1

Ich habe auf die ${FILENAME}_${EXTENSION}oben erwähnte Syntax umgestellt .

Früher habe ich verwendet, $()wenn ich zwei Variablen mit einem Unterstrich verketten musste. Zum Beispiel, $YYYYMMDD$()_$HHMMSSum einen Dateinamen zu generieren, der einen Zeitstempel im Format JJJJMMTT_HHMMSS enthält. Die Mitte $()gibt nichts zurück und zerlegt die beiden Variablen.

Ich habe verwendet time, um die Zuweisungen mit der $YYYYMMDD$()_$HHMMSSMethode und einigen der oben genannten zu messen , und sie haben alle 0 ms auf dem alten Server gemeldet, auf dem ich dies verwende. Leistung scheint kein Problem zu sein.


Das beantwortet die Frage nicht. Sie sollten dafür eine neue Frage stellen. $()gibt eine Unterschale in ein paar Schalen auf (einige optimieren sie weg). Es entführt auch einen Operator für etwas, für das es nicht entwickelt wurde. ${x}_yist was du willst.
Stéphane Chazelas

Was meinst du mit "Das beantwortet die Frage nicht"? Es ist keine gute Antwort, aber es ist eine Antwort.
Scott

Bearbeitet, um Mehrdeutigkeiten zu beseitigen.
user208145

0

Sie sollten Variablen in Kleinbuchstaben verwenden (dies ist die beste Vorgehensweise).
Also verwende ich Dateiname und Erweiterung anstelle von FILENAME und EXTENSION

Wenn Sie sagen, dass der Dateiname aus einer Datei gelesen wird, gehe ich davon aus, dass das Skript wie folgt lautet:

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

Und dass Sie beide Variablen $ filename und $ extension mit einem Unterstrich verketten wollen _.
Die von Ihnen angegebenen Beispiele (außer: no double \) funktionieren hier korrekt:

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

Wie einige andere:

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

Ihr Problem ist also nicht, wie die Variablen zusammenhalten, sondern mit dem Inhalt der Variablen. Es scheint vernünftig zu denken, dass dies:

read -r filename  <file.txt

liest einen abschließenden Wagenrücklauf, \rwenn aus einer Windows-Datei gelesen wird .

Eine einfache Lösung (für ksh, bash, zsh) besteht darin, alle Steuerzeichen aus der gelesenen Variablen zu entfernen:

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

Dies könnte mit einem Wert simuliert werden, der einen Wagenrücklauf hat:

$ 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

Oder ersetzen Sie den Wert von filename:

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

Fazit.

Also das:

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

Erhält den korrekten Wert nameauch dann, wenn die anderen Variablen Steuerzeichen enthalten.



-2

Sie können dies auch verwenden: Trennen Sie die einzelnen Variablen durch Leerzeichen und verknüpfen Sie sie mit tr, um das Leerzeichen zu entfernen.

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) Diese Frage wurde bereits mehr als ausreichend beantwortet. (2) Was macht Ihre Antwort, wenn die vorhandene Variable Sonderzeichen enthält?
G-Man sagt, dass Monica

Hiermit wird das Problem mit der Variablen, die einen Wagenrücklauf enthält, nicht behoben. Außerdem werden Leerzeichen entfernt, was möglicherweise nicht gewünscht ist.
Kusalananda

@ Kusalananda: Eigentlich, es sei denn, ich überseh etwas, dies behandelt Wagenrücklauf ganz gut; Leerzeichen sind das einzige Problem.
G-Man sagt, dass Monica
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.