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并行运行这些行,因为将有数百万个输出文件,如本应用程序中所述.
谢谢你的想法.
您可以使用剪切和排序来提取组,然后使用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)