linux - 当使用 5 个输入文件时,bash xargs 加上 bash Paste 可以输出正好 3 个文件吗?

标签 linux bash awk xargs

也许 xargs 可以做到这一点,也许不能,但这似乎是可能的。该解决方案根本不需要使用 xargs。更喜欢所有 bash 命令,但不喜欢 python。不过,它必须处理大量输入文件(此处仅显示玩具大小的示例),因此不要尝试预先将所有文件的内容加载到内存中。

起始输入是文本文件“docs.txt”中的 5 个文件名,全部位于一列中:

[ga@sam ~]$ cat docs.txt
a.1.txt
a.2.txt
b.1.txt
c.1.txt
c.2.txt

所需的输出正好是 3 个文件:输出文件 a.doc 将按此顺序包含 a.1.txt 和 a.2.txt 的内容。输出文件b.doc:b.1.txt的内容。输出文件c.doc:按顺序排列文件c.1.txt和c.2.txt的内容。

我当前正在做的是 xargs 正在接收 3 行输入,并且 gnu Paste 连接每行上列出的文件的内容。我希望 xargs 能够准确输出 3 个文本文件,每个 xargs 输入行一个,根据解释的每个分组依据值如上所示命名,但我还没有找到窍门。

这是迄今为止的代码:

[ga@sam ~]$ cat docs.txt | awk -F. '{ORS=" "}NR==1 {prev=$1; print; next} prev!=$1{print "\n";}{prev=$1}1' | xargs -L 1 paste -s
my cat
has fleas
my dog is clean
the bat
ate a rat
[ga@sam ~]$ cat docs.txt | awk -F. '{ORS=" "}NR==1 {prev=$1; print; next} prev!=$1{print "\n";}{prev=$1}1' # | xargs -L 1 paste -s
a.1.txt a.2.txt
 b.1.txt
 c.1.txt c.2.txt [ga@sam ~]$
[ga@sam ~]$ cat docs.txt | awk -F. '{ORS=" "}NR==1 {prev=$1; print; next} prev!=$1{print "\n";}{prev=$1}1' | xargs -L 1 -P 0 --process-slot-var=f paste -s > "$f".doc
xargs: unrecognized option '--process-slot-var=f'

这里 awk 的目的只是对文件名的第一个字段进行分组(如 SQL 分组)。这样,每个组都希望创建一个准确的输出文件。

这里粘贴的目的就像cat一样。我将按顺序将文件连接在一起就是全部。如果我们想使用 cat 而不是 Paste,它可能也能工作,只是比 Paste 慢一点,并且 cat 命令在 3 次调用中看起来像这样:

cat a.1.txt a.2.txt > a.doc
cat b.1.txt > b.doc
cat c.1.txt c.2.txt > c.doc

但是就像我试图解释的那样,我不想提前显式编码 3 行 cat 行,因为它将是动态确定的输出文件数量,完全基于输入文件中找到的组。

即使我将 xargs 升级到最新版本,我仍然预计无法使用如上所示编写的代码生成恰好 3 个输出文件。 xargs -process-slot-var 似乎会根据系统特性生成许多文件,而不是此应用程序中的 3 个文件,更重要的是,输出文件的数量直接根据实际应用程序中找到的组数量而变化。

如果单行代码不起作用,我也许可以使用某种循环结构(在 awk 中?)来进行一些变量替换,最终为每个输出文件发出一行 bash 命令。我不太了解 awk 来发出命令。如果这样做,我更喜欢 bash Parallel 并行运行这些行,因为如本应用程序中所述,将有数百万个输出文件。

感谢您的想法。

最佳答案

您可以使用剪切和排序来提取组,然后使用 while read 循环将组文件组合在一起:

cut -d. -f1 docs.txt |
  sort -u |
  while read -r group; do cat "$group".*.txt > "$group".doc; done

另外,简单的 bash

while IFS=. read -r group rest; do
    cat "$group.$rest" >> "$group.doc"
done < docs.txt

或普通 awk

awk -F. '{
    f = $1 ".doc"
    while (( getline line < $0 ) > 0)
        print line > f
    close($0)
}' docs.txt

关于linux - 当使用 5 个输入文件时,bash xargs 加上 bash Paste 可以输出正好 3 个文件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53377270/

相关文章:

regex - 匹配模式后提取第 N 行

linux - www 文件夹内的 .ssh/authorized_keys 文件

bash - 根据文件输出创建名称/值对

awk - 如何通过升序(列)对文件重新排序?

linux - 在 shell 脚本中使用查找

如果键字段匹配,Bash 连接字段

linux - 如何删除 X 字符前的所有单词

android - 无法使用套接字显示接收到的缓冲区

linux - 在Linux中使用空格设置环境变量

linux - Kubernetes与Linux之间的兼容性