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

Geo*_*son -2 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
Run Code Online (Sandbox Code Playgroud)

所需的输出正好是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输入行一个,如上所示基于每个group-by值进行命名,如上所述,但我没有找到诀窍.

这是迄今为止的代码:

[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'
Run Code Online (Sandbox Code Playgroud)

这里awk的目的只是为了实现分组(如SQL groupby)文件名的第一个字段.这样,希望每个组都能获得一个输出文件.

粘贴的目的就像猫一样.我将顺序连接文件就是全部.如果我们想要使用cat而不是粘贴,它可能也可以正常工作,如果比粘贴慢一点,并且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
Run Code Online (Sandbox Code Playgroud)

但就像我试图解释的那样,我不想提前编写明确的3个猫行代码,因为它将是一个动态确定的输出文件数,完全基于输入文件中找到的组.

即使我将我的xargs升级到最新版本,我仍然期望一个关键的无法生成正好3个输出文件,我的代码如上所示.xargs -process-slot-var似乎在此应用程序中基于系统特性而不是3来生成许多文件,更重要的是,输出文件的数量直接因实际应用程序中找到的组数而异.

如果单行程不起作用,我可能会回退使用某种循环结构(在awk中?)做一些变量替换,最终每个输出文件发出一行bash命令.我不知道awk是否足以发出命令.如果以这种方式完成,我宁愿bash parallel并行运行这些行,因为将有数百万个输出文件,如本应用程序中所述.

谢谢你的想法.

gle*_*man 5

您可以使用剪切和排序来提取组,然后使用while循环读取组文件:

cut -d. -f1 docs.txt |
  sort -u |
  while read -r group; do cat "$group".*.txt > "$group".doc; done
Run Code Online (Sandbox Code Playgroud)

还有,朴素的bash

while IFS=. read -r group rest; do
    cat "$group.$rest" >> "$group.doc"
done < docs.txt
Run Code Online (Sandbox Code Playgroud)

或简单的awk

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