如何交错两个文件中的列?

时间:2017-08-31 00:06:52

标签: join text awk merge

假设我们有两个文件(大小相同的m * n矩阵),其中包含列:

A1, A2, A3, A4, ..., An 

B1, B2, B3, B4, ..., Bn 

预期输出为:

A1, B1, A2, B2, A3, B3, A4, B4, ..., An, Bn 

如何做到这一点?我想有一些awk单行,但我无法构建正确的单行...

6 个答案:

答案 0 :(得分:2)

awk '
    BEGIN { FS=OFS=", " }
    NR==FNR { a[NR]=$0; next }
    {
        split(a[FNR],f)
        for (i=1;i<=NF;i++) {
            printf "%s%s%s%s", f[i], OFS, $i, (i<NF?OFS:ORS)
        }
    }
' a.txt b.txt

答案 1 :(得分:1)

在我的测试中,这样的东西似乎没问题,因为两个文件的行数和行数相同=数组维度相同:

$ cat file1
a1,a2,a3
a4,a5,a6

$ cat file2
b1,b2,b3
b4,b5,b6

$ awk 'NR==FNR{f1[FNR]=$0;next};{split(f1[FNR],ff1,",");split($0,ff2,","); \
for (f=1;f<=length(ff1);f++) printf ff1[f]","ff2[f](f!=length(ff1)?",":"\n")}' file1 file2
a1,b1,a2,b2,a3,b3
a4,b4,a5,b5,a6,b6

快速解释:
awk首先读取一个文件,然后读取第二个文件 NR==FNR{f1[FNR]=$0;next}:读取第一个文件并创建一个数组f1,其中包含file1的行号和内容整行$ 0

第一个文件完成后,在处理file2期间执行其余代码:

split(f1[FNR],ff1,","):由于两个文件具有相同数量的行,因此这些文件将以前的读取记录从file1(存储在数组f1中)拆分为新数组ff1,方法是使用逗号作为拆分分隔符。

split($0,ff2,","):类似地,这将$ 0 =当前记录/当前行file2拆分为名为ff2的数组,使用逗号作为分隔符。

for (f=1;f<=length(ff1);f++) printf ff1[f]","ff2[f](f!=length(ff1)?",":"\n")
这个遍历ff1的数组元素(ff1具有相同的ff2长度)并从ff1和ff2打印数据。

(f!=length(ff1)?",":"\n"):当我们没有到达数组ff1 / ff2的末尾时会打印逗号,,否则会打印换行符\n

答案 2 :(得分:0)

如果您的输入建议您只使用每行输入的一行,那么按记录处理可能比按字段处理更容易。您可以通过stdin读取一个文件,并明确读取另一个文件。

作为一个班轮,这可能看起来像这样:

awk 'BEGIN {ORS=RS=","} {print $1; getline < "f2"; print $1}' f1; echo

通过评论更容易阅读:

awk '
  BEGIN { ORS=RS="," }     # record separator is a comma!
  {
    print $1               # print a trimmed (1-field) record from the first file,
    getline < "file2"      # then get the next record from the second file.
    print $1               # print a record from the second file.
  }
' file1
echo                       # print a newline, since awk didn't.

如果您希望输出在逗号后面有空格,则可以将BEGIN块中的代码替换为:

  BEGIN {RS=","; ORS=", "}

答案 3 :(得分:0)

使用trrs reshape a data array ),如果有的话。如果没有,请与您当地的管理员联系或破解这个星球。首先,测试数据:

$ cat foo bar
a1,a2,a3
b1,b2,b3

将其发送到tr替换,空格:

$ cat foo bar | tr , ' '
a1 a2 a3
b1 b2 b3

并转到rs进行转置:

$ cat foo bar | tr , ' ' | rs -T
a1  b1
a2  b2
a3  b3

最后到另一个rs挤压前一行:

$ cat foo bar | tr , ' ' | rs -T | rs 1
a1  b1  a2  b2  a3  b3

上次rs可以替换为tr \n' ' 'rs尊重输入和输出的分隔符​​,请参阅手册页。我故意把逗号留下了。

答案 4 :(得分:0)

粘贴 + tr + sed Unix shell的技巧:

file1内容:

A1, A2, A3, A4, A5, A6, A7

file2内容:

B1, B2, B3, B4, B5, B6, B7
paste <(tr ',' '\n' <file1) <(tr ',' '\n' <file2) | paste -s | sed 's/[[:space:]]\+/, /g'

输出:

A1, B1, A2, B2, A3, B3, A4, B4, A5, B5, A6, B6, A7, B7

答案 5 :(得分:0)

使用awkpaste的另一种解决方案不会受到损害。

paste -d',' file1 file2 | awk -F ',' '{ 
    z = ""
    for (i=1; i <= NF/2; ++i){ 
        x = i+(NF/2)
        y = $i","$x
        z = z","y
    }
    print substr(z,2,length(z))
}' 

首先,paste -d',' file1 file2将两个文件放在同一行索引下,并使用相同的字段分隔符= ,合并它们。

然后,在awk中,-F ','以逗号作为字段分隔符,并遍历1/2个列索引i <= NF/2,找到对应的列以交织x = i+(NF/2)并使用两个值y = $i","$x创建一个新的逗号分隔字符串。最后,将这些新字符串连接到一个空字符串z = z","y中,并在循环之后(不包括第一个逗号print substr(z,2,length(z))的情况下打印)。

我个人认为,这比以前使用awk的某些解决方案更为明确。