ไฟล์เนื้อหาลงในตัวแปร unix พร้อมขึ้นบรรทัดใหม่


118

ฉันมีไฟล์ข้อความ test.txt ที่มีเนื้อหาต่อไปนี้:

text1
text2 

และฉันต้องการกำหนดเนื้อหาของไฟล์ให้กับตัวแปร UNIX แต่เมื่อฉันทำสิ่งนี้:

testvar=$(cat test.txt)
echo $testvar

ผลลัพธ์คือ:

text1 text2

แทน

text1
text2 

ใครช่วยแนะนำวิธีแก้ปัญหานี้ให้ฉันได้ไหม

คำตอบ:


186

การมอบหมายงานไม่ได้ลบอักขระขึ้นบรรทัดใหม่ แต่เป็นการechoทำเช่นนี้ คุณต้องใส่เครื่องหมายคำพูดรอบ ๆ สตริงเพื่อรักษาบรรทัดใหม่เหล่านั้น:

echo "$testvar"

สิ่งนี้จะให้ผลลัพธ์ที่คุณต้องการ ดูการถอดเสียงต่อไปนี้สำหรับการสาธิต:

pax> cat num1.txt ; x=$(cat num1.txt)
line 1
line 2

pax> echo $x ; echo '===' ; echo "$x"
line 1 line 2
===
line 1
line 2

เหตุผลว่าทำไมการขึ้นบรรทัดใหม่จะถูกแทนที่ด้วยช่องว่างที่ไม่ได้ทั้งหมดจะทำอย่างไรกับechoคำสั่งค่อนข้างจะเป็นรวมกันของสิ่ง

เมื่อกำหนดบรรทัดคำสั่งให้bashแยกออกเป็นคำตามเอกสารสำหรับIFSตัวแปร:

ไอเอฟเอ:ภายในสนามแยกที่ใช้สำหรับการแยกคำหลังจากที่ขยายตัว ... <space><tab><newline>ค่าเริ่มต้นคือ

ซึ่งระบุว่าโดยค่าเริ่มต้นสามารถใช้อักขระสามตัวใดก็ได้ในการแบ่งคำสั่งของคุณออกเป็นแต่ละคำ หลังจากนั้นตัวคั่นคำจะหายไปสิ่งที่คุณเหลือคือรายการคำ

รวมเข้ากับechoเอกสาร ( bashคำสั่งภายใน) แล้วคุณจะเห็นว่าเหตุใดจึงมีช่องว่างออกมา:

echo [-neE] [arg ... ]:ส่งออก args คั่นด้วยช่องว่างตามด้วยขึ้นบรรทัดใหม่

เมื่อคุณใช้echo "$x"จะบังคับให้xตัวแปรทั้งหมดเป็นคำเดียวตามbashดังนั้นจึงไม่แยก คุณสามารถดูได้ด้วย:

pax> function count {
...>    echo $#
...> }
pax> count 1 2 3
3
pax> count a b c d
4
pax> count $x
4
pax> count "$x"
1

ที่นี่countฟังก์ชันจะพิมพ์จำนวนอาร์กิวเมนต์ที่ระบุ 1 2 3และa b c dสายพันธุ์ที่แสดงให้เห็นในการกระทำ

แล้วเราลองกับทั้งสองรูปแบบในxตัวแปร หนึ่งโดยไม่ต้องคำพูดที่แสดงให้เห็นว่ามีสี่คำ"test", "1", และ"test" "2"เพิ่มคำพูดที่ทำให้มันเป็นหนึ่งใน"test 1\ntest 2"คำเดียว


คำพูด ... นั่นคือสิ่งที่ฉันขาดหายไป! ขอบคุณ!
anonymite

สิ่งที่น่าสังเกต: การขึ้นบรรทัดใหม่ต่อท้ายจะถูกลบออกโดยตัวดำเนินการแทนคำสั่ง: ลองออนไลน์!
โยนาห์

11

เนื่องจากตัวแปรIFS (Internal Field Separator)ซึ่งมีการขึ้นบรรทัดใหม่

$ cat xx1
1
2

$ A=`cat xx1`
$ echo $A
1 2

$ echo "|$IFS|"
|       
|

วิธีแก้ปัญหาคือการรีเซ็ต IFS ไม่ให้มีการขึ้นบรรทัดใหม่ชั่วคราว :

$ IFSBAK=$IFS
$ IFS=" "
$ A=`cat xx1` # Can use $() as well
$ echo $A
1
2
$ IFS=$IFSBAK

เพื่อคืนการเปลี่ยนแปลงที่น่าสยดสยองของ IFS

IFS=$IFSBAK

ฉันได้ทำการเปลี่ยนแปลงนี้แล้ว แต่ตอนนี้สิ่งอื่น ๆ ของฉันใช้งานไม่ได้โปรดบอกให้ฉันรีเซ็ตกลับ?
Pooja25

หากคุณไม่ต้องการให้ไปที่ตัวแปรให้ใช้ซับเดียวโดยตรง:echo "$(IFS=''; cat text.txt)"
Curtis Yallop

10

Bash -ge 4 มี mapfile ในตัวเพื่ออ่านบรรทัดจากอินพุตมาตรฐานไปยังตัวแปรอาร์เรย์

help mapfile 

mapfile < file.txt lines
printf "%s" "${lines[@]}"

mapfile -t < file.txt lines    # strip trailing newlines
printf "%s\n" "${lines[@]}" 

ดูสิ่งนี้ด้วย:

http://bash-hackers.org/wiki/doku.php/commands/builtin/mapfile


3

หากมีคนสนใจตัวเลือกอื่น:

content=( $(cat test.txt) )

a=0
while [ $a -le ${#content[@]} ]
do
        echo ${content[$a]}
        a=$[a+1]
done

3

testvar=$(cat test.txt)ตัวแปรของคุณตั้งอย่างถูกต้องโดย หากต้องการแสดงตัวแปรนี้ซึ่งประกอบด้วยอักขระขึ้นบรรทัดใหม่เพียงแค่ใส่เครื่องหมายคำพูดคู่เช่น

echo "$testvar" 

นี่คือตัวอย่างทั้งหมด:

$ printf "test1\ntest2" > test.txt
$ testvar=$(<test.txt)
$ grep testvar <(set)
testvar=$'test1\ntest2'
$ echo "$testvar"
text1
text2
$ printf "%b" "$testvar"
text1
text2

0

envdirยูทิลิตี้ให้เป็นวิธีที่ง่ายต่อการทำเช่นนี้ envdirใช้ไฟล์เพื่อแสดงตัวแปรสภาพแวดล้อมโดยมีการแมปชื่อไฟล์กับชื่อไฟล์ env var และการแม็พเนื้อหาไฟล์กับค่า env var หากเนื้อหาของไฟล์มีการขึ้นบรรทัดใหม่ env var.

ดูhttps://pypi.python.org/pypi/envdir

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