合并两个文件中的每隔一行

合并两个文件中的每隔一行

文件1:

A
B
C 
D

文件2:

E
F
G
H

我如何获得输出:

A
BF
C
DH

答案1

你可以这样做:

paste -d '\n' file1 file2 | sed -n 'p;n;n;N;s/\n//p' > output

paste压缩两个文件,每个文件交替一行,并sed p打印第一个文件,丢弃第二个文件,将第四个文件附加到第三个文件,然后将它们连接起来并再次从下一行开始。

或者使用 GNU sed

paste -d '\n' file1 file2 | sed '2~4d' | paste -sd '\n\0\n' - > output

其中sed仅从d压缩输出中提取每 4 行中的第二行paste,然后第二次粘贴进行连接。

或者,仍然使用 GNU sed

sed 'z;n' file2 | paste -d'\0' file1 - > output

其中sedzaps 一行(在其他sed实现中,您可以使用s/.*//)并获取并打印next,以便我们可以将其粘贴到 file1。

答案2

$ awk '{ getline other <"file2" } { print $0 (FNR % 2 == 0 ? other : "") }' file1
A
BF
C
DH

对于file1读取的每一行,此awk脚本还会从中读取一行file2并将其存储在变量 中other。然后,它继续打印file1与变量连接的行other,如果行号是奇数,则不打印任何内容。


一个 shell 循环可以做同样的事情:

n=0
while IFS= read -r a; do
    n=$(( n + 1 ))

    IFS= read -r b <&3

    [ "$(( n % 2 ))" -ne 0 ] && b=""
    printf '%s%s\n' "$a" "$b"
done <file1 3<file2

此循环循环file1,每行都被读入,并且每次迭代还会从(通过文件描述符 3)$a读取一行到。如果到目前为止读取的行数是奇数,则设置为空字符串。然后将两者都打印出来。file2$bfile1$b$a$b


使用paste和 GNU sed,并假设两个文件都不包含制表符(因为它们在问题中不包含制表符):

paste file1 file2 | sed '1~2s/\t.*//;s/\t//'

paste并排生成两个文件的内容,并用制表符分隔。该sed表达式将首先删除奇数行上制表符开始的所有内容,然后删除所有剩余的制表符。

在相同的假设下,sed上面的整个命令可以替换为awk

paste file1 file2 | awk -F '\t' '{ print $1 (FNR % 2 == 0 ? $2 : "") }'

答案3

使用

awk 'NR==FNR {a[NR]=$0;next} FNR%2==0 { a[FNR]=a[FNR]$0}  END{for ( i in a) print a[i]}' file1 file2

例如

#!/bin/bash
echo "a
B
C
D" > file1
echo 'aa
Gd
Er
Yu
Ee
Tt' > file2
awk 'NR==FNR {a[NR]=$0;next} FNR%2==0 { a[FNR]=a[FNR]$0}  END{for ( i in a) print a[i]}' file1 file2

你会得到输出

a
BGd
C
DYu
Tt

答案4

使用GNU sed,我们可以这样做:

sed -e 'R file2' file1 | sed -Ee 'N;N;N;s/\n.*(\n.*)\n/\1/'

其中我们模拟pastevia sed,然后将4行串在一起并以这样的方式进行操作,以便删除第2行并删除第3行和第4行之间的换行符。对下一个 4 行槽重复此过程。

相关内容