Shell脚本-读取文件的两行,并读取另一个文件的一行

Shell脚本-读取文件的两行,并读取另一个文件的一行,shell,Shell,喂,我有两个文件 文件1包含: line1 line2 line3 line4 line5 line6 line7 line8 line9 line10 anotherline1 anotherline2 anotherline3 文件2包含: line1 line2 line3 line4 line5 line6 line7 line8 line9 line10 anotherline1 anotherline2 anotherline3 我想做一个while循环,以便将其输出到文件3

喂,我有两个文件

文件1包含:

line1
line2
line3
line4
line5
line6
line7
line8
line9
line10
anotherline1
anotherline2
anotherline3
文件2包含:

line1
line2
line3
line4
line5
line6
line7
line8
line9
line10
anotherline1
anotherline2
anotherline3
我想做一个while循环,以便将其输出到文件3:

line1
line2
anotherline1
line3
line4
anotherline2
line5
line6
anotherline3
line7
line8
anotherline1
line9
line10
anotherline2
我在这里寻找答案,但我不知道怎么做。 我必须说我对shell脚本非常在行

另外:“while循环”应该一直持续到文件1的末尾。不管File2有多长,实际上,在我个人的场景中,File2总是比File1短。输出应为:File1Line1、File1Line2、File2Line1、File1Line3、File1Line4、File2Line2。。。。等

有什么帮助吗

注意:如果之前已经回答过,那么mods请关闭此问题。在谷歌搜索了几个小时后,我就是找不到任何答案


编辑:添加了何时结束循环的说明。

我不知道有什么方便的方法可以在纯shell脚本中完成特定的操作。您最好只编写一个python/perl/etc.脚本。类似于这个awk脚本的东西可以工作,但有点混乱:

awk '{
  print; getline; print; 
  if (!getline < "file2") { 
    close("file2");
    getline < "file2"
  };
  print
}' file1
awk'{
打印;获取行;打印;
如果(!getline<“file2”){
关闭(“文件2”);
getline<“文件2”
};
打印
}'文件1

打印;getline;print
将打印文件1中的下一行,获取该行之后的行,然后打印它。
如果(!getline<“file2”)
尝试从file2读取下一行,如果失败,则关闭它,隐式重新打开它,并从file2读取第一行。最后的
打印
将打印文件2中的那一行(下一行或第一行)。

在本机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
while:;做
read-r line1此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
(感谢):


如果我正确地解释了你的问题,你想

  • 逐步执行
    file1
    start to finish,然后
  • 在每两行之后插入
    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
    
    #/usr/bin/env bash
    mapfile-t file2
    这样做的缺点是将所有
    file2
    作为数组加载到内存中。如果因为文件太大而出现问题,您可以添加一些shell glop,以便在每次调用循环时查找特定的行,尽管这会非常慢。更好的是,更具体地定义你的问题,或者考虑替代的工具!p>
    另外请注意,
    mapfile
    命令是一个bash-4-ism,因此如果您使用的是较旧的Linux或OSX(仍然随bash 3提供),则需要一个不同的解决方案。。。或者是对bash的升级。

    解释一下你的一行程序是如何工作的将是非常有教育意义的!:-)因此,如果我在末尾添加>file3,输出将是我想要的?我现在就试试…(说清楚点,我唯一反对的是,这不能在纯壳中实现的说法——请看我的答案作为反例——否则就很好了)。@ghoti补充了一个解释。现在读起来容易多了。我喜欢这个答案的简单逻辑。向上投票:)顺便说一句——如果两个输入文件中的行数不匹配(file2中的一行对应file1中的每两行),您希望如何执行此操作?“while循环”应该一直持续到file1的末尾。不管File2有多长,实际上,在我个人的场景中,File2总是比File1短。输出应为:File1Line1、File1Line2、File2Line1、File1Line3、File1Line4、File2Line2。。。。你可以考虑把它编辑到你的问题中去;它显著地改变了正确答案的构成。在我们到达文件2的末尾后,是否应该为原本应该从中产生的行保留空格,还是应该将其忽略?添加到问题中。谢谢,我的错^_^乌西斯(第一个例子)正是我想要的。虽然如果到达文件2的末尾,while也会结束,我希望它一直运行,直到文件1的所有行都被读取。继续运行,做什么?在文件2中的内容本来应该是空的地方添加空行?只需从文件1添加更多行?第一个示例修改为忽略文件2上的EOF。@user3246010,啊。必须重新阅读一下这个问题,才能得出您希望从头开始使用file2的结论。如果你能用英语而不是仅仅用例子来说明,你会很感激的。你从哪里得到这种“回头看”的行为?我看不到任何规范(除了程序不能在那一点退出)。可以考虑在这里指定BASH 4。x的需要,使用<代码> MaPrase< /Cord>。(顺便说一句,有很多简单的方法可以在文件2结束时重新打开它;你可以
    阅读这个!!!这正是我想要的。如果我把我的问题弄得太复杂了,我真的很抱歉。但这肯定解决了它。谢谢!!@CharlesDuffy,关于bash 4的要点很好-我修改了这个答案。关于“简单的方法”,我认为多个文件句柄是比数组更高级的脚本功能,因此对于不熟悉其使用的人来说可能不会“更容易”。谢谢你的建议。这是一个golfed版本,有趣的是
    awk'FNR==NR{a[n++]=$0;next}1;!(FNR%2){print a[I++%n]}file2 file1
    Wow这更好(在答复中添加)。