将流输出保存为多个文件

save stream output as multiple files

我有一个程序 (pull) 下载文件并将其内容 (JSON) 发送到标准输出,程序的输入是我要下载的每个文档的 ID,比如所以:

pull one two three
>
> { ...one }
> {
    ...two
  }
> { ...three }

但是,我现在想为它发出的每个文件将该输出通过管道传输到不同的文件,理想情况下能够按照最初使用的 args 的顺序引用文件名:one two three.

所以,我正在寻找的结果应该如下所示。

pull one two three | > .json
>
> saved one.json
> saved two.json
> saved three.json

有什么方法可以实现这个或类似的东西吗?

更新

我只是想阐明程序的工作原理,以及为什么循环遍历参数并为声明的每个参数多次执行程序可能不是理想的。

每当 pull 被执行时,它会执行两个操作:

  1. A:昂贵的操作(及时解决):这将检索数据库中可用的所有文档,我们可以通过调用 pull.
  2. 时提供的参数名称
  3. B:特定于提供的参数的操作:在A解析后,我们将使用它的响应来获取所需的数据用于专门检索单个文档。

这意味着,为每个参数多次调用 A+B 并不理想,因为 A 是一项昂贵的操作。

所以我不想 AB AB AB AB 我想要 ABBBB.

你做得很辛苦。

for f in one two three; do pull "$f" > "$f.json" & done

除非脚本中的某些内容与多个同步副本不兼容,否则这也会使过程更快。如果是,只需将 & 更改为 ;

更新

尝试只写单个文件。如果您还需要能够将它们发送到 stdout,只需 cat 文件,或者在写入时使用 tee

如果不行,那么你需要清楚地识别和解析数据块。例如,如果一个部分的开始是唯一的地方 { 出现在一行中的 first 字符,这是一个不错的标记值。使用它把你的输出拆分成文件。

例如,把这个扔到另一个脚本中:

awk 'NR==FNR { ndx=1; split([=11=],fn); name=""; next; } /^{/ { name=fn[ndx++]; } { if (length(name)) print [=11=] > name".json"; }' <( echo "$@" ) <( pull "$@" )

使用 one two three 调用该脚本,它应该会执行您想要的操作。

说明

awk '...' <( echo "$@" ) <( pull "$@" )

这会执行两个命令,returns 它们的输出为“文件”,输入流供 awk 处理。第一个只是将提供的参数列表放在一行中,以便 awk 加载到数组中。第二个使用这些参数执行您的 pull 脚本,它提供您已经获得的流输出。

NR==FNR { ndx=1; split([=13=],fn); name=""; next; }

这告诉 awk 初始化文件控制索引,从 echo 命令(args)中读取单行并将它们分成所需的文件名数组,然后跳过其余的处理该记录(它不是“数据”,它是元数据,我们已经完成了它。)我们将 name 初始化为一个空字符串,以便我们可以检查长度 - 否则那些前导空白行最终会在.json,这可能不是您想要的。

/^{/ { name=fn[ndx++]; }

这告诉 awk 每次看到 { 作为一行的第一个字符时,将输出文件名基址设置为当前索引(我们在上面初始化为 1)并递增下次索引。

{ if (length(name)) print [=15=] > name".json"; }

这告诉 awk 将每一行打印到一个文件,该文件的名称与当前索引指向的名称相同,并附加“.json”。 if (length(name)) 在 JSON.

的第一个块之前丢弃前导空行

结果是每个新集都会根据您给定的参数触发一个新文件名。

这对你有用吗?

正在使用

$: ls *.json
ls: cannot access '*.json': No such file or directory

$: pull one two three # my script to simulate output

{ ...one... }
{
  ...two...
}
{ ...three... }

$: splitstream one two three # the above command in a file to receive args

$: grep . one* two* three* # now they exist
one.json:{ ...one... }
two.json:{
two.json:  ...two...
two.json:}
three.json:{ ...three... }