我想将文本文件的不同行读取到不同的变量。例如
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
在 for 循环中使用。这似乎不起作用。
答案1
你会这样做:
unset -v line1 line2
{ IFS= read -r line1 && IFS= read -r line2; } < input.txt
或者:
{ line1=$(line) && line2=$(line); } < input.txt
(效率较低,因为line
很少内置,并且大多数 shell 需要 fork 来实现命令替换。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
但请注意,与大多数其他 shell 相反,bash
数组索引从 0 而不是 1 开始(继承自ksh
),因此第一行将位于${line[0]}
,而不是${line[1]}
(尽管正如@Costas 所示,你可以让readarray
(又名mapfile
)开始在索引 1 处写入值(bash
数组也与大多数其他 shell 的情况相反)疏数组)与-O 1
)。
也可以看看:理解“IFS=读取-r行”吗?
答案2
我建议使用数组来完成此类任务
mapfile -t -O 1 var <input.txt
所以你会得到每一行${var[1]}
,${var[2]}
依此类推
答案3
严格来说这并不是您所要求的,但它可能适合您的需求。您可以使用 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