如何将文件的不同行读取到不同变量?


14

我想将文本文件的不同行读取到不同的变量。例如

input.txt

line1 foo foobar bar
line2 bar
line3 foo
line4 foobar bar

我想这个结果存储在变量var1var2var3var4这样

var1=line1 foo foobar bar
var2=line2 bar

等等。

有人可以告诉我它是如何完成的。我试图eval在for循环中使用。它似乎不起作用。



3
这是一个不好的方法。由于基本上是唯一的理由来设置变量是做一些与他们,并且因为有专门的工具了广大设计做的事情,在一个文件中的文本的每一行(awk中,桑达,grepcut,等人),它要好得多,只是你需要做什么。不要在shell脚本中进行微管理;编排工具以完成工作。
通配符

Answers:


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

但是请注意,与大多数其他shell相反,bash数组索引从0开始而不是1(从继承ksh),因此第一行将位于${line[0]},而不是${line[1]}(尽管@Costas已显示,您可以使readarray(aka mapfile)开始在indice写入值1(bash数组也与大多数其他shell的稀疏数组相反-O 1)。

另请参见:了解“ IFS =读取-r行”吗?


12

我愿意将数组用于此类任务

mapfile -t -O 1 var <input.txt

这样您将在每一行中都有${var[1]}${var[2]}依此类推


这种单线效果很好。为我解决了这个问题。
马特·扎博尼克

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将整个输入文件转换为bash脚本,然后再将其作为源。我对quote()在做什么有一个模糊的想法。更具描述性的变量名将有所帮助。您能再解释一下吗?
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.