วิธีอ่านบรรทัดต่าง ๆ ของไฟล์ไปยังตัวแปรต่าง ๆ


14

ฉันต้องการที่จะอ่านบรรทัดที่แตกต่างกันของไฟล์ข้อความไปยังตัวแปรที่แตกต่างกัน ตัวอย่างเช่น

input.txt:

line1 foo foobar bar
line2 bar
line3 foo
line4 foobar bar

ฉันต้องการผลนี้จะถูกเก็บไว้ในตัวแปรvar1, var2, var3และvar4เช่นว่า

var1=line1 foo foobar bar
var2=line2 bar

และอื่น ๆ

ใครช่วยได้โปรดบอกฉันว่ามันจะทำอย่างไร ฉันพยายามที่จะใช้evalในวงสำหรับ ดูเหมือนจะไม่ทำงาน



3
นี่เป็นวิธีการที่ไม่ดี ตั้งแต่พื้นเหตุผลเดียวที่จะตัวแปรชุดที่จะทำอะไรบางอย่างกับพวกเขาและเนื่องจากมีจำนวนมากมายของเครื่องมือโดยเฉพาะการออกแบบมาเพื่อทำสิ่งที่มีบรรทัดของข้อความในทุกไฟล์ (Awk, Sed, grep, cut, et. al.) มันดีกว่ามากที่จะทำสิ่งที่คุณต้องทำ อย่าใช้ micromanage ในเชลล์สคริปต์ จัดเตรียมเครื่องมือเพื่อให้งานสำเร็จลุล่วง
สัญลักษณ์แทน

คำตอบ:


20

คุณต้องการ:

unset -v line1 line2
{ IFS= read -r line1 && IFS= read -r line2; } < input.txt

หรือ:

{ line1=$(line) && line2=$(line); } < input.txt

(มีประสิทธิภาพน้อยลงเนื่องจากlineไม่ค่อยมีในตัวและเชลล์ส่วนใหญ่จำเป็นต้องแยกเพื่อนำการทดแทนคำสั่งมาใช้และlineไม่ได้เป็นคำสั่งมาตรฐานอีกต่อไป)

วิธีใช้ลูป:

unset -v line1 line2 line3
for var in line1 line2 line3; do
  IFS= read -r "$var" || break
done < input.txt

หรือเพื่อกำหนดชื่อของตัวแปรโดยอัตโนมัติline<++n>ดังนี้:

n=1; while IFS= read -r "line$n"; do
  n=$((n + 1))
done < input.txt

โปรดทราบว่าbashสนับสนุนตัวแปรอาเรย์และreadarrayบิวอินเพื่ออ่านบรรทัดลงในอาเรย์:

readarray -t line < input.txt

อย่างไรก็ตามโปรดทราบว่าตรงกันข้ามกับเชลล์อื่น ๆ ส่วนใหญ่bashดัชนีอาเรย์เริ่มต้นที่ 0 ไม่ใช่ 1 (สืบทอดมาจากksh) ดังนั้นบรรทัดแรกจะอยู่ใน${line[0]}ไม่ใช่${line[1]}(แม้ว่าจะเป็น @Costas ได้แสดงไว้แล้วคุณสามารถทำให้readarray(aka mapfile) เริ่มเขียนค่าที่ดัชนี 1 ( bashอาร์เรย์ยังตรงกันข้ามกับเชลล์อื่น ๆ ส่วนใหญ่ที่เป็นอาร์เรย์เบาบาง ) ด้วย-O 1)

ดูเพิ่มเติมที่: เข้าใจ "IFS = read -r line" หรือไม่


12

ฉันเสนอให้ใช้อาร์เรย์สำหรับงานดังกล่าว

mapfile -t -O 1 var <input.txt

ดังนั้นคุณจะต้องในแต่ละบรรทัด${var[1]}, ${var[2]}และอื่น ๆ


หนึ่งซับนี้ทำงานได้ดีมาก แก้ไขปัญหาให้ฉัน
Matt Zabojnik

0

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

awk '
function quote(str,   d, m, x, y, z) {
  d = "\47"; m = split(str, x, d)
  for (y in x) z = z d x[y] (y < m ? d "\\" d : d)
  return z
}
{
  print $1 "=" quote($0)
}
' input.txt > /tmp/input.sh
. /tmp/input.sh

ผลลัพธ์:

$ echo "$line1"
line1 foo foobar bar

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