如何将两个文件中的两行添加到一个命令中?

时间:2016-12-26 05:32:34

标签: linux bash shell

我还在空闲时间学习bash,而我正在尝试做的是格式化一个文件,列出一次两行直接相关的数据并将这些数据插入到一个命令中...例如:我的列表文件 -

line 1 data
line 2 data related to line 1
line 3 data
line 4 data related to line 3

现在我要做的是找到一种方法将相关的行添加到单个命令中,并继续将下两行添加到所述命令等,直到列表完成。数据将作为选项插入命令...

COMMAND --OPTION1=line1data --OPTION2=line2data

不应重复列表,也不应重复任何数据行。到目前为止,我所做的是使用grep将文件格式化为两个单独的文件,第一个文件仅列出第一行数据(没有以下第二行相关数据),即line1 line3 line5等,以及第二个文件包含第二行相关数据的列表,即第2行第4行等等......现在我可能正在为自己努力,但我试图将这两个文件中的数据放入命令中比如for命令循环过程...但我不知道如何获取每个格式化文件的第一行(然后获取每个文件的下一行)并将其插入一个命令...

所以我在这里。另外,无论如何都要使这更容易,只需从文件中取两行数据并将其输入命令?提前致谢

2 个答案:

答案 0 :(得分:3)

一种方法是:

while read opt1; do
  read opt2
  COMMAND --OPTION1="$opt1" --OPTION2="$opt2"
done < input.txt

你可能在这里看到逻辑 - 我们有一个循环,它在变量opt1中读取一行,其中循环中的第一个命令将下一行消耗到变量opt2中,并且然后使用这两个变量来构造命令行。这样做,它是一个简单的bash单线程(或POSIX shell - 这里没有什么是bash独有的。)

另一种解决方法是使用paste命令,该命令不是严格意义上的bash的一部分,而是随操作系统一起提供的。请注意以下事项:

$ printf '1\n2\n3\n4\n5\n6\n' | paste - -
1   2
3   4
5   6

这并没有按照你在问题中表达的方式分开使用的东西,所以一个更复杂的循环是有序的。默认情况下,paste使用标签作为分隔符。假设您的输入数据不包含制表符,您可以使用如下构造:

while IFS=$'\t' read opt1 opt2; do
  COMMAND --OPTION1="$opt1" --OPTION2="$opt2"
done < <(paste - - < input.txt)

这里的逻辑是paste命令将为我们的read命令构造单行输入,这些命令将其IFS设置为paste使用的相同分隔符。 {b}中的<( ... )构造称为“Process Substitution”(您可以在手册页中找到它),如果您希望while循环填充将在以后使用的变量,这将非常有用在shell脚本中..但是你可以通过使用管道来避免这种基础:

paste - - < input.txt | while IFS=$'\t' read opt1 opt2; do
  COMMAND --OPTION1="$opt1" --OPTION2="$opt2"
done

请注意,生成选项卡的构造$'\t'(通常称为“格式替换”,但在bash手册页的“QUOTING”部分中描述)也可能不是通用的,但确实存在在除了bash之外的许多其他shell中,所以它仍然相当便携。

虽然它有点长并涉及额外的命令,但我认为第二种方法是最清晰和可读的。你应该使用对你最有意义的方法,这样你将来可以更容易地维护它。

考虑使用-r选项进行读取,处理反斜杠和行继续是否有益或有问题。我不知道你的用例,所以除了你知道之外,我不能对此做出推荐。

答案 1 :(得分:1)

假设您的文件input.txt包含以下内容

1
2
3
4
5
6
7
8

使用awk命令访问各行,如下所示:

awk '{if(NR%2 == 0) {print "COMMAND --OPTION1="data1" --OPTION2="$0;}else{data1=$0;}}' input.txt

在上面的awk命令中,NR是变量,它保存当前行号。 $0是完整的一行。

NR%2表示使用mod NR运算符检查2给出的行号是否可被%整除。

  • 如果NR%2 equals 0那么NR给出的行都是偶数,即2,4,6,8 ......

  • 如果NR%2 not equals 0那么NR给出的行都是奇数编号,即1,3,5,7 ......

    Output:    
    COMMAND --OPTION1=1 --OPTION2=2
    COMMAND --OPTION1=3 --OPTION2=4
    COMMAND --OPTION1=5 --OPTION2=6
    COMMAND --OPTION1=7 --OPTION2=8