Bash:循环多个文件并打印每个文件的每一行并写入不同的文件

0 shell bash shell-script

我有 3 个文件,行数不同。我试图循环遍历这三个文件,并将每个文件的第一行打印到新文件 output1.txt 中,然后将每个文件的第二行打印到另一个新文件 output2.txt 中,依此类推。由于每个文件的行数不同,如果几行没有 file2 和 file3 的条目,则它应该忽略并在创建的后续输出文件中不打印任何内容。我怎样才能在 bash 中实现这一目标?

文件1

xyz
abc
def
ghi
jkl
Run Code Online (Sandbox Code Playgroud)

文件2

123
456
789
Run Code Online (Sandbox Code Playgroud)

文件3

ax1
by2
Run Code Online (Sandbox Code Playgroud)

输出文件

输出1.txt

xyz
123
ax1
Run Code Online (Sandbox Code Playgroud)

输出2.txt

abc
456
by2
Run Code Online (Sandbox Code Playgroud)

输出3.txt

def
789
Run Code Online (Sandbox Code Playgroud)

输出4.txt

ghi
Run Code Online (Sandbox Code Playgroud)

输出5.txt

jkl
Run Code Online (Sandbox Code Playgroud)

cas*_*cas 6

使用bash告诉awk去做这件事,这就是 bash 的用途(而不是,例如,本身进行文本处理)。

例如,以下 awk 单行语句将每个输入行写入由文字字符串“output”、当前输入文件的当前行号(awk 变量FNR)和文字字符串“.txt”构造的文件名:

$ awk '{print > "output" FNR ".txt"}' file*

$ tail output*
==> output1.txt <==
xyz
123
ax1

==> output2.txt <==
abc
456
by2

==> output3.txt <==
def
789

==> output4.txt <==
ghi

==> output5.txt <==
jkl
Run Code Online (Sandbox Code Playgroud)

注意:如果您有大量输出文件(数百个或更多),您可能会遇到问题。对于某些版本的 awk,如果超出了内核和登录环境允许进程的文件句柄数,则进程可能会因错误而终止。对于其他版本的 awk(例如 GNU awk),它在管理在任何给定时刻打开哪些文件句柄进行写入时可能会减慢速度。除非您的某些输入文件长达数百行,否则这不太可能成为问题。

以下内容适用于任何版本的 awk 以及任何长度的输入文件(因为它一次只打开一个输出文件进行写入),但速度会明显变慢,因为它会为每次写入打开输出文件并立即关闭它写完后。即便如此,它仍然比在 shell 中执行此操作快许多倍。

awk '{
  # use 5-digit zero-padded output filenames for this version
  # e.g. output00001.txt
  out = sprintf("output%05i.txt", FNR);

  if (out in files) {
    # we have written to this file before, so append to it
    print >> out
  } else {
    # first write to this file, so create or truncate it.
    print > out
    files[out]=1
  }
  close(out)
}' file*
Run Code Online (Sandbox Code Playgroud)