İki değişkeni alt çizgi ile birleştirme


54

Alt çizgileri olan bir dosya adı oluşturmak için iki değişkeni birleştirmem gerekiyor. Değişkenlerimi $FILENAMEve $EXTENSIONdosya isminin bir dosyadan okunduğu yeri arayalım .

FILENAME=Hello
EXTENSION=WORLD.txt

Şimdi ...

Aşağıdakileri başarı olmadan denedim:

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

Ben her zaman bir tür garip çıktı alırım. Genellikle ilk önce alt çizgi olur.

Olmam gerek

echo $NAME
Hello_WORLD.txt

2
Muhtemelen betiğinizde satır başı karakterleri var.
Stéphane Chazelas

Evet öyleydi. : D
Rhyuk

Yanıtlar:


67

Böyle bir şey kullanabilirsiniz:

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

Bu da işe yarıyor:

NAME=${FILENAME}_${EXTENSION}

1
Sorun, NAME adlı kullanıcıyı okuduğum dosyaydı. Windows biçimlendirme ... Çözümünüz bundan sonra çok iyi çalıştı. Teşekkürler
Rhyuk

2
İlk komut değişkenin değerini ve bir komut değişikliğinin kullanımını yönetir ve echomuhtemelen yardımcı olamaz. İkinci komut zaten soruda verildi.
Gilles 'SO- kötülük' dur '27

1
Evet! Onu seviyorum. Bu beni en uzun süre sinir bozuyordu. Çözüm için teşekkürler!
racl101

Bu benim için çalışıyor. '$ FILENAME_ $ EXTENSION' kullandığımda, yalnızca '$ EXTENSION' değerleri görünür. Lütfen bunun neden olduğunu açıklamaya yardımcı olur musunuz? Teşekkürler
Lei Hao

12

Sizin:

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

hepsi iyi, öyleyse:

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

(ama kesinlikle değil NAME=$(echo ${FILENAME}_${EXTENSION}) olarak kullandığıecho ve operatör ).split+glob

NAME=$FILENAME_$EXTENSION

aynı olurdu:

NAME=${FILENAME_}${EXTENSION}

as _( \veya aksine ') değişken ismindeki geçerli bir karakterdir.

Sorununuz, sadece LF yerine CRLF ile sınırlandırılmış çizgiler olması, bu değişken içeriğin CR karakterinde bitmesi anlamına geliyordu.

CR karakteri bir terminale yazıldığında terminale imleci satırın başına getirmesini söyler. Yani Hello<CR>_WORLD.TXT<CR>bir terminale gönderildiğinde _WORLD.TXT(geçersiz kılma Hello) olarak gösterecekti .


1

${FILENAME}_${EXTENSION}Yukarıda belirtilen sözdizimini kullanmaya geçtim .

Ben kullanmak için kullanılan $()Ben bir alt çizgi ile iki değişken bitiştirmek için gerektiğinde. Örneğin, $YYYYMMDD$()_$HHMMSSYYYYMMDD_HHMMSS biçiminde bir zaman damgası içeren bir dosya adı oluşturmak için. Orta $()hiçbir şey döndürmez ve iki değişkeni birbirinden ayırır.

Ben kullandım timekullanarak atamaları ölçmek için $YYYYMMDD$()_$HHMMSSyöntem ve yukarıda olanların bazıları ve hepsi bu konuda kullanıyorum eski sunucuda 0ms bildirdik. Performans bir sorun gibi görünmüyor.


Bu soruya cevap vermiyor. Bunun için yeni bir soru sormalısın. $()bir mermiyi birkaç mermiye yerleştirir (bazıları onu optimize eder). Aynı zamanda bir operatör için dizayn edilmemiş bir şeyi kaçırıyor. ${x}_yİstediğin şey bu.
Stéphane Chazelas

Ne demek “bu soruyu cevaplamaz”. Harika bir cevap değil ama bir cevap.
Scott

Belirsizliği ortadan kaldırmak için düzenlenmiştir.
user208145

0

Değişkenleri küçük harf olarak kullanmalısınız (en iyi uygulamadır).
Bu yüzden FILENAME ve EXTENSION yerine dosya adını ve uzantısını kullanacağım

“Dosya adı bir dosyadan okunur” dediğiniz gibi, betiğin şöyle olduğunu varsayacağım:

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

Ve hem değişkenleri $ dosyaadı hem de $ eklentisini bir alt çizgi ile birleştirmek istediğinizde _.
Sağladığınız örnekler (hariç: çift değil \) burada doğru çalışır:

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

Diğerleri gibi:

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

Yani, probleminiz değişkenlerin nasıl birbirine yapışması ile değil, değişkenlerin içeriğiyle ilgilidir. Bunu düşünmek mantıklı görünüyor:

read -r filename  <file.txt

\rBir windows dosyasından okunuyorsa izleyen bir satır başı okuyacaktır .

Basit bir çözüm (ksh, bash, zsh için) tüm kontrol karakterlerini okuma değişkeninden kaldırmaktır:

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

Bu satır başı getirisi olan bir değerle simüle edilebilir:

$ 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

Veya değeri değiştirerek filename:

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

Sonuç.

Yani bu:

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

nameDiğer değişkenler kontrol karakterleri içermesine rağmen doğru değeri elde eder .



-2

Bunu da kullanabilirsiniz: boşlukları ayırmak için ayrı değişkenleri ayırın ve boşlukları kaldırmak için tr kullanarak bunları birleştirin.

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) Bu soru zaten yeterince cevaplanmış durumda. (2) Mevcut değişken içinde özel karakterler varsa, cevabınız ne yapar?
G-Man

Bu satır başı içeren değişkenle ilgili sorunu çözmez. Ayrıca, istenmeyebilecek olan alanları da kaldırır.
Kusalananda

@Kusalananda: Aslına bakarsanız, bir şeye göz yummadığım sürece, bu durum taşıma dönüşünü iyi yapıyor; tek sorun boşluklar.
G-Man,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.