我还在空闲时间学习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命令循环过程...但我不知道如何获取每个格式化文件的第一行(然后获取每个文件的下一行)并将其插入一个命令...
所以我在这里。另外,无论如何都要使这更容易,只需从文件中取两行数据并将其输入命令?提前致谢
答案 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