ฉันจะอ่านตัวแปรจากไฟล์ได้อย่างไร


68

ฉันต้องการแทรกค่า (สตริง) ในสคริปต์ที่ฉันจะอ่านจากไฟล์ข้อความ

ตัวอย่างเช่นแทนที่จะเป็น:

echo "Enter your name"
read name

ฉันต้องการอ่านสตริงจากไฟล์ข้อความอื่นดังนั้นล่ามควรอ่านสตริงจากไฟล์ไม่ใช่ที่ผู้ใช้ป้อน


1
ไฟล์ข้อความของคุณมีหน้าตาเป็นอย่างไร? ไฟล์ทั้งหมดเป็น 1 ตัวแปรหรือว่าพวกเขาKEY=VALUEจับคู่? การแก้ปัญหาจะแตกต่างกันมาก (ถ้าเป็นหลังคำตอบของ Takkat ใช้อดีตของ Radu)
kiri

1
@CiroSantilli ไม่ใช่ crossposted หากมีการโพสต์โดยผู้ใช้อื่นไม่มีสิ่งเช่น "การข้ามไซต์ซ้ำกัน" สิ่งเดียวที่ควรหลีกเลี่ยงคือเดียวกันคำถามที่ถามโดยเดียวกันผู้ใช้ในเว็บไซต์ต่างๆ
terdon

คำตอบ:


98

หากต้องการอ่านตัวแปรจากไฟล์เราสามารถใช้คำสั่งsourceหรือ.

ให้ถือว่าไฟล์มีบรรทัดต่อไปนี้

MYVARIABLE="Any string"

จากนั้นเราสามารถนำเข้าตัวแปรนี้โดยใช้

#!/bin/bash

source <filename>
echo $MYVARIABLE

16
เหตุผลหนึ่งที่คุณอาจไม่ต้องการทำแบบนี้ก็เพราะว่าสิ่งใดก็ตามที่อยู่ใน<filename>นั้นจะถูกเรียกใช้ในเชลล์ของคุณเช่นrm -rf /ซึ่งอาจเป็นอันตรายมาก
Mark Ribau

3
ไปงานปาร์ตี้สาย แต่ไม่ไม่ควรทำเครื่องหมายหรือเป็นคำตอบ แหล่งนี้เป็นแหล่งไฟล์ bash อื่นซึ่งไม่ใช่สิ่งที่ OP ขอ เขาถามวิธีการอ่านเนื้อหาของไฟล์ลงในตัวแปร ไม่ใช่วิธีการที่จะดำเนินการสคริปต์อื่นซึ่งกำหนดตัวแปร คำตอบที่ถูกต้องคือคำตอบด้านล่าง name = $ (cat "$ file")
HörmannHH

2
OTOH มันเป็นคำตอบสำหรับคำถามที่ฉันถาม google และ google นำมาให้ฉันที่นี่ ครั้งแปลกใช่มั้ย
Michael Terry

1
ยอดเยี่ยมใช้ได้กับตัวแปรหลายตัว! จุดของ @MarkRibau นั้นเป็นที่เข้าใจกัน แต่ฉันเดาว่าถ้าคุณพูดถูกไฟล์ในสคริปต์อื่นและต้องผ่านมันไปให้ดีและควบคุมมัน
madlymad

1
คุณสามารถใช้sedเพื่อเพิ่มlocalคำหลักและทำให้สคริปต์เป็นบิตที่ปลอดภัยและไม่ polute ขอบเขตทั่วโลกของคุณ ดังนั้นภายในฟังก์ชัน AA ทำแล้วใช้cat global_variables.sh | sed -e 's/^/local /' > local_variables.sh . ./local_variables.shสิ่งที่คุณนำเข้าในฟังก์ชั่นจะมีให้เฉพาะในฟังก์ชั่นนั้น โปรดทราบว่ามันglobal_variables.shมีเพียงหนึ่งตัวแปรต่อบรรทัด
Nux

55

เมื่อพิจารณาว่าคุณต้องการให้เนื้อหาทั้งหมดในไฟล์ข้อความของคุณถูกเก็บไว้ในตัวแปรคุณสามารถใช้:

#!/bin/bash

file="/path/to/filename" #the file where you keep your string name

name=$(cat "$file")        #the output of 'cat $file' is assigned to the $name variable

echo $name               #test

หรือในทุบตีบริสุทธิ์:

#!/bin/bash

file="/path/to/filename"     #the file where you keep your string name

read -d $'\x04' name < "$file" #the content of $file is redirected to stdin from where it is read out into the $name variable

echo $name                   #test

ฉันไม่ต้องการแสดงตัวแปรฉันต้องการให้สคริปต์นี้อ่านได้สำหรับการประมวลผลเพิ่มเติม ฉันลอง awk ที่อ่านทีละบรรทัด
user208413

1
echo $name ตกลงลบ ฉันใช้มันเพื่อการทดสอบ ถัดไปคุณสามารถใช้$nameตัวแปรสำหรับการประมวลผลเพิ่มเติมทุกที่ที่คุณต้องการในสคริปต์ของคุณ
Radu Rădeanu

ฉันไม่สามารถใช้ที่ใดก็ได้เป็นสคริปต์ของฉันเพราะสคริปต์ไม่รู้จักค่าของตัวแปร ในกรณีของเราชื่อตัวแปร
user208413

6
@ user208413 ค่าของ$nameตัวแปรคือสตริงจากไฟล์ของคุณที่กำหนดโดยใช้cat $fileคำสั่ง อะไรไม่ชัดเจนหรือยากที่จะเข้าใจ
Radu Rădeanu

1
มันซ้ำซ้อนในการใช้$fileตัวแปรแยกหากคุณใช้เพียงครั้งเดียวเพื่อโหลด$nameตัวแปรใช้cat /path/to/file
kiri

11

จากภายในสคริปต์ของคุณคุณสามารถทำได้:

read name < file_containing _the_answer

คุณสามารถทำได้หลายครั้งเช่นในวง

while read LINE; do echo "$LINE"; done < file_containing_multiple_lines

หรือสำหรับไฟล์ที่มีหลายรายการในแต่ละบรรทัด . . grep -v ^ # file | ในขณะที่อ่าน abc; ทำเสียงก้อง a = $ ab = $ bc = $ c; เสร็จสิ้น
gaoithe

7

อีกวิธีหนึ่งในการทำเช่นนี้คือเพียงแค่เปลี่ยนเส้นทางอินพุตมาตรฐานไปยังไฟล์ของคุณซึ่งคุณมีอินพุตของผู้ใช้ทั้งหมดตามลำดับที่โปรแกรมคาดไว้ ตัวอย่างเช่นกับโปรแกรม (เรียกว่าscript.sh)

#!/bin/bash
echo "Enter your name:"
read name
echo "...and now your age:"
read age

# example of how to use the values now stored in variables $name and $age
echo "Hello $name. You're $age years old, right?"

และไฟล์อินพุต (เรียกว่าinput.in)

Tomas
26

คุณสามารถเรียกใช้จากเทอร์มินัลด้วยหนึ่งในสองวิธีต่อไปนี้:

$ cat input.in | ./script.sh
$ ./script.sh < input.in

และมันจะเทียบเท่ากับการเรียกใช้สคริปต์และป้อนข้อมูลด้วยตนเอง - มันจะพิมพ์บรรทัด "Hello Tomas คุณอายุ 26 ปีใช่มั้ย"

ในฐานะที่เป็นRadu Rădeanuได้แนะนำแล้วคุณสามารถใช้catภายในสคริปต์ของคุณในการอ่านเนื้อหาของไฟล์ลงใน avariable ใช้ - ในกรณีที่คุณต้องการแต่ละไฟล์จะมีเพียงหนึ่งเส้นมีเพียงค่าที่คุณต้องการสำหรับตัวแปรเฉพาะที่ ในตัวอย่างข้างต้นคุณจะต้องแยกไฟล์อินพุตให้เป็นไฟล์เดียวกับชื่อ (พูด, name.in) และอีกไฟล์หนึ่งเป็นไฟล์อายุ (พูด, age.in) และเปลี่ยนread nameและและread ageบรรทัดเป็นname=$(cat name.in) และage=$(cat age.in)ตามลำดับ


ฉันมีสคริปต์ต่อไปนี้: vh = awk "NR == 3 {print; exit}" /var/www/test/test.txt ฉันอ่านบรรทัดที่ 3 จากไฟล์ข้อความชื่อ test.txt เมื่อฉันได้รับสตริงฉันต้องการใช้สตริงนี้เป็นอินพุตสำหรับการสร้างไดเรกทอรี
user208413

1
vh=$(awk "NR==3 {print;exit}" /var/www/test.txt)เปลี่ยนที่ จากนั้นคุณจะได้รับการบันทึกสตริงในตัวแปร$vhดังนั้นคุณสามารถใช้มันได้เช่น: mkdir "/var/www/$vh"- สิ่งนี้จะสร้างโฟลเดอร์ที่มีชื่อที่ระบุไว้ภายใน / var / www
Tomas Aschan

ฉันได้ทำวิธีนี้แล้วแต่ยังไม่สามารถสร้างโฟลเดอร์ :(
user208413

@ user208413: คุณได้รับข้อความแสดงข้อผิดพลาดอะไร "มันใช้งานไม่ได้" คือน่าเสียดายที่ไม่ใช่คำอธิบายปัญหาที่เป็นประโยชน์มาก ...
Tomas Aschan


3
name=$(<"$file") 

จากman bash:1785การทดแทนคำสั่งนี้เทียบเท่าname=$(cat "$file")แต่เร็วกว่า



0

หากคุณต้องการใช้หลายสายคุณสามารถไปกับ:

path="/foo/bar";
for p in `cat "$path"`;
do echo "$p" ....... (here you would pipe it where you need it) 

หรือ

หากคุณต้องการให้ผู้ใช้ระบุไฟล์

read -e "Specify path to variable(s): " path;
for p in 'cat "$path"';
do echo "$p" ............................


0

ฉันใช้สิ่งนี้เพื่อรับตัวแปรเดียวจากไฟล์

GET_VAR=$(grep --color=never -Po "^${GET_VAR}=\K.*" "${FILE}" || true)

เมื่อGET_VARไม่พบในมันจะว่างเปล่าแทนที่จะก่อให้เกิดข้อผิดพลาดขอบคุณไป${FILE}|| true

มันใช้grep -Pซึ่งอยู่ใน grep GNU แต่ไม่ได้เริ่มต้นใน grep ทั้งหมดในเวลาที่เขียนนี้


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