การเชื่อมโยงสองตัวแปรเข้ากับขีดล่าง


54

ฉันต้องต่อตัวแปรสองตัวเข้าด้วยกันเพื่อสร้างชื่อไฟล์ที่มีเครื่องหมายขีดล่าง ให้เรียกตัวแปรของฉัน$FILENAMEและ$EXTENSIONอ่านชื่อไฟล์จากไฟล์

FILENAME=Hello
EXTENSION=WORLD.txt

ตอนนี้ ...

ฉันได้ลองทำสิ่งต่อไปนี้โดยไม่ประสบความสำเร็จ:

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

ฉันมักจะได้ผลลัพธ์ที่แปลก ๆ โดยทั่วไปแล้วจะขีดเส้นใต้ก่อน

ฉันต้องการมัน

echo $NAME
Hello_WORLD.txt

2
อาจเป็นสคริปต์ของคุณที่มีอักขระขึ้นบรรทัดใหม่
Stéphane Chazelas

ใช่นั่นแหละ : D
Rhyuk

คำตอบ:


67

คุณสามารถใช้สิ่งนี้:

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

วิธีนี้ใช้ได้ผลเช่นกัน:

NAME=${FILENAME}_${EXTENSION}

1
ปัญหาคือไฟล์ที่ฉันอ่าน NAME การจัดรูปแบบ Windows ... โซลูชันของคุณทำงานได้ยอดเยี่ยมหลังจากนั้น ขอบคุณ
Rhyuk

2
คำสั่งแรกจะทำให้ค่าของตัวแปรและการใช้การทดแทนคำสั่งและechoอาจช่วยไม่ได้ คำสั่งที่สองได้รับแล้วในคำถาม
Gilles 'หยุดความชั่วร้าย' ใน

1
ใช่ ฉันรักมัน. นี่ทำให้ฉันรำคาญใจเป็นเวลานาน ขอบคุณสำหรับการแก้ปัญหา!
racl101

มันใช้งานได้สำหรับฉัน เมื่อฉันใช้ '$ FILENAME_ $ EXTENSION' จะมีเฉพาะค่าของ '$ EXTENSION' ปรากฏขึ้น คุณช่วยอธิบายได้ไหมว่าทำไมสิ่งนี้ถึงเกิดขึ้น ขอบคุณ
Lei Hao

12

ของคุณ:

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

ทุกอย่างเรียบร้อยดีดังนั้นจะเป็น:

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

( แต่แน่นอนไม่ NAME=$(echo ${FILENAME}_${EXTENSION})เป็นมันใช้echoและผู้ประกอบการ )split+glob

NAME=$FILENAME_$EXTENSION

จะเป็นเช่นเดียวกับ:

NAME=${FILENAME_}${EXTENSION}

ในฐานะที่เป็น_(ตรงกันข้าม\หรือ') เป็นตัวละครที่ถูกต้องในชื่อตัวแปร

ปัญหาของคุณคือคุณมีเส้นที่คั่นด้วย CRLF แทนที่จะเป็นแค่ LF ซึ่งหมายความว่าเนื้อหาตัวแปรเหล่านั้นจบลงด้วยอักขระ CR

อักขระ CR เมื่อเขียนไปยังเทอร์มินัลบอกให้เทอร์มินัลเลื่อนเคอร์เซอร์ไปที่จุดเริ่มต้นของบรรทัด ดังนั้นHello<CR>_WORLD.TXT<CR>เมื่อส่งไปยังเทอร์มินัลจะแสดงเป็น_WORLD.TXT(แทนที่Hello)


1

ฉันเปลี่ยนเป็นการใช้${FILENAME}_${EXTENSION}ไวยากรณ์ที่กล่าวถึงข้างต้น

ฉันเคยใช้$()เมื่อฉันต้องการเชื่อมต่อสองตัวแปรเข้ากับขีดล่าง ตัวอย่างเช่นใน$YYYYMMDD$()_$HHMMSSการสร้างชื่อไฟล์ที่มีการประทับเวลาในรูปแบบของ YYYYMMDD_HHMMSS ตรงกลาง$()ไม่มีอะไรส่งคืนและแยกตัวแปรทั้งสองออกจากกัน

ฉันเคยtimeวัดการบ้านโดยใช้$YYYYMMDD$()_$HHMMSSวิธีการและที่กล่าวมาข้างต้นและพวกเขาทั้งหมดรายงาน 0ms บนเซิร์ฟเวอร์เก่าที่ฉันใช้งานอยู่ ดูเหมือนว่าประสิทธิภาพจะไม่เป็นปัญหา


ไม่ตอบคำถาม คุณควรตั้งคำถามใหม่สำหรับสิ่งนั้น $()ทำการแยก subshell ในเชลล์ไม่กี่อัน (บางอันปรับให้เหมาะสม) นอกจากนี้ยังเป็นการแย่งชิงโอเปอเรเตอร์สำหรับบางสิ่งที่ไม่ได้รับการออกแบบมา ${x}_yคือสิ่งที่คุณต้องการ
Stéphane Chazelas

คุณหมายถึงอะไร“ ไม่ตอบคำถาม” มันไม่ใช่คำตอบที่ดี แต่เป็นคำตอบ
สกอตต์

แก้ไขเพื่อลบความกำกวม
user208145

0

คุณควรใช้ตัวแปรเป็นตัวพิมพ์เล็ก (เป็นแนวปฏิบัติที่ดีที่สุด)
ดังนั้นฉันจะใช้ชื่อไฟล์และส่วนขยายแทน FILENAME และ EXTENSION

ดังที่คุณพูดว่า“ ชื่อไฟล์อ่านจากไฟล์” ฉันจะสมมติว่าสคริปต์คือ:

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

และที่คุณต้องการที่จะเชื่อมตัวแปรทั้งสอง $ ชื่อไฟล์และ $ _ส่วนขยายที่มีการขีดเส้นใต้
ตัวอย่างที่คุณให้ (ยกเว้น: ไม่มี double \) ทำงานอย่างถูกต้องที่นี่:

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

ในขณะที่อื่น ๆ :

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

ดังนั้นปัญหาของคุณไม่ได้อยู่ที่ว่าตัวแปรเชื่อมโยงกันอย่างไร แต่มีเนื้อหาของ vars ด้วย ดูเหมือนว่าสมเหตุสมผลที่จะคิดว่าสิ่งนี้:

read -r filename  <file.txt

จะอ่าน carriage trailing return \rถ้าอ่านจากไฟล์ windows

วิธีแก้ปัญหาง่ายๆ (สำหรับ ksh, bash, zsh) คือการลบอักขระควบคุมทั้งหมดออกจากตัวแปรอ่าน:

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

สิ่งนี้อาจจำลองด้วยค่าที่มีการคืนค่าขนส่ง:

$ 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

หรือแทนที่ค่าของfilename:

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

ข้อสรุป

ดังนั้นนี่คือ:

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

จะได้รับค่าที่ถูกต้องnameแม้ว่า vars อื่นจะมีอักขระควบคุม



-2

นอกจากนี้คุณยังสามารถใช้สิ่งนี้: แยก vars แยกต่างหากด้วยช่องว่างและเชื่อมต่อโดยใช้ tr เพื่อลบช่องว่าง

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) คำถามนี้ได้รับคำตอบมากกว่าเพียงพอแล้ว (2) คำตอบของคุณจะทำอย่างไรถ้าตัวแปรที่มีอยู่มีอักขระพิเศษอยู่ในนั้น
G-Man

สิ่งนี้ไม่ได้แก้ไขปัญหาที่เกิดขึ้นกับตัวแปรที่มีการคืนค่าขนส่ง นอกจากนี้ยังลบช่องว่างบางสิ่งที่อาจไม่ต้องการ
Kusalananda

@ Kusalananda: จริงๆแล้วถ้าฉันไม่สามารถมองเห็นบางสิ่งบางอย่างนี้จะจัดการการรับคืนรถได้ดี ช่องว่างเป็นปัญหาเดียว
G-Man
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.