说,我有两个文件。
File1包含:
line1
line2
line3
line4
line5
line6
line7
line8
line9
line10
和File2包含:
anotherline1
anotherline2
anotherline3
我想做一个while循环,以便将它输出到File3:
line1
line2
anotherline1
line3
line4
anotherline2
line5
line6
anotherline3
line7
line8
anotherline1
line9
line10
anotherline2
我在这里搜索了答案,但我无法弄清楚如何去做。 我必须说我在shell脚本中非常棒...
另外:“while循环”应该是到达file1的结尾。无论File2有多长,实际上,在我的个人场景中,File2总是比File1短。输出应该是:File1Line1,File1Line2,File2Line1,File1Line3,File1Line4,File2Line2 ......等等
任何帮助?
注意:如果之前已经回答过,那么mods请关闭这个问题。谷歌搜索几个小时后我找不到任何答案。
编辑:添加了关于何时结束循环的说明。
答案 0 :(得分:3)
如果我正确地解释你的问题,你想要
file1
,然后file2
的“下一行”,每当内容不足时,再转回file2
的顶部。如果这是目标,你可以通过多种方式使用awk,但下面的shell片段可能会这样做。
#!/usr/bin/env bash
mapfile -t file2 < file2
max=${#file2[@]}
while read line; do
((count++))
echo "$line"
if [[ $((count%2)) == 0 ]]; then
if [[ next -ge max ]]; then
next=0
fi
echo "${file2[next++]}"
fi
done < file1
这有一个缺点是将所有file2
作为数组加载到内存中。如果这是一个问题因为文件太大,你可以添加一些shell glop来在循环的每个调用中找到特定的行,尽管这将是非常慢的。更好的是,更具体地定义您的问题,或考虑替代工具! : - )
另请注意,mapfile
命令是bash-4-ism,因此如果您使用的是较旧的Linux或OSX(仍然附带bash 3),则需要使用其他解决方案。 ..或升级到bash。
答案 1 :(得分:2)
我不知道在纯shell脚本中执行特定操作的便捷方法。你可能最好只写一个python / perl / etc。脚本。像这个awk脚本的东西会起作用,但它有些混乱:
awk '{
print; getline; print;
if (!getline < "file2") {
close("file2");
getline < "file2"
};
print
}' file1
print; getline; print
将从file1打印下一行,然后获取该行,然后打印它。 if (!getline < "file2")
尝试从file2读取下一行,如果失败,则关闭它,隐式重新打开它,并从file2读取第一行。最终print
将从file2(下一个或第一个)打印该行。
答案 2 :(得分:2)
这个awk应该可以工作:
awk 'FNR==NR{a[++i]=$0; next} FNR%2{p=$0; curr=(FNR==1 || curr==i) ? 1 : curr+1; next}
{print p ORS $0 ORS a[curr]}' file2 file1
line1
line2
anotherline1
line3
line4
anotherline2
line5
line6
anotherline3
line7
line8
anotherline1
line9
line10
anotherline2
编辑:更短awk
(感谢@geirha):
awk 'FNR==NR{a[n++]=$0;next}1;!(FNR%2){print a[i++%n]}' file2 file1
答案 3 :(得分:1)
在原生shell中轻松完成 - 无需awk
等外部工具。打开两个文件描述符,绑定到不同的文件,并迭代两者。
while :; do
read -r line1 <&3 && printf '%s\n' "$line1" || break
read -r line2 <&3 && printf '%s\n' "$line2" || break
read -r line3 <&4 || { exec 4<file2 && read -r line3 <&4; }
printf '%s\n' "$line3"
done 3<file1 4<file2 1>file3
在这种情况下,3
是我们打开file1
的文件描述符号,4
是我们打开file2
的文件描述符号。 1>file3
,或简称为>file3
,将文件描述符1
(也称为stdout)的输出重新路由到输出文件。
如果您愿意,可以选择其他数字,但只保证3-9之间的范围可以在所有POSIX shell上免费使用。 (0-2是stdin,stdout和stderr; shell可以使用10以上的内容供自己使用,尽管在较新且更现代的shell中很少出现这种情况。)