2

我想替换这个:

          }
      ]
  }
  {
      "commits":[

和:

          },

使用bash.

上面的文本是bash脚本本身(而不是文件)中解析的。“输入”是git log由 4 个不同的管道命令解析的内容,这些命令将输出咀嚼并吐出到文件中。管道看起来像这样:

git log (...) | paste (...) | tail (...) | awk (...) > output.file

到目前为止,我的策略是添加一个额外的管道和一个将 a 替换为 a 的命令,multi-line pattern例如single-line pattern

git log (...) | paste (...) | tail (...) | awk (...) | 'replace-multiline' (...) > output.file

换句话说,我还没有找到正确的replace-multiline命令。也许你能帮助我?;)

我试过的

我已经用了三天时间尝试不同的旋转,awk甚至(声称解决多行搜索和替换挑战的那些)。他们都没有在我的背景下工作。我不精通这些命令中的任何一个,所以我一直在黑暗中进行刺激。我真的很感激任何指示!sedgrepperl

背景

我正在编写一个输出到有效输出的bash脚本( github 上的项目)。当脚本从存储库的根目录运行时它工作得很好,但我想扩展它以便它从包含所有存储库的目录运行,因此在一次调用中以格式输出所有存储库的格式。git logJSONgit logJSON

该脚本已移至父目录并在每个子目录(即git存储库)上运行,返回以下输出(该脚本还用于将存储库名称作为每个对象项中的属性输出)。

当前输出:

  {
      "commits":[
          {
              "repository":"repo1",
              "commit_nr":"1",
              /* ... */
          },
          {
              "repository":"repo1",
              "commit_nr":"2",
              /* ... */
          },
          {
              "repository":"repo1",
              "commit_nr":"3",
              /* ... */
          }
      ]
  }
  {
      "commits":[
          {
              "repository":"repo2",
              "commit_nr":"1",
              /* ... */
          },
          {
              "repository":"repo2",
              "commit_nr":"2",
              /* ... */
          },
          {
              "repository":"repo2",
              "commit_nr":"3",
              /* ... */
          }
      ]
  }
  {
      "commits":[
          {
              "repository":"repo3",
              "commit_nr":"1",
              /* ... */
          },
          {
              "repository":"repo3",
              "commit_nr":"2",
              /* ... */
          },
          {
              "repository":"repo3",
              "commit_nr":"3",
              /* ... */
          }
      ]
  }

想要的输出:

  {
      "commits":[
          {
              "repository":"repo1",
              "commit_nr":"1",
              /* ... */
          },
          {
              "repository":"repo1",
              "commit_nr":"2",
              /* ... */
          },
          {
              "repository":"repo1",
              "commit_nr":"3",
              /* ... */
          },
          {
              "repository":"repo2",
              "commit_nr":"1",
              /* ... */
          },
          {
              "repository":"repo2",
              "commit_nr":"2",
              /* ... */
          },
          {
              "repository":"repo2",
              "commit_nr":"3",
              /* ... */
          },
          {
              "repository":"repo3",
              "commit_nr":"1",
              /* ... */
          },
          {
              "repository":"repo3",
              "commit_nr":"2",
              /* ... */
          },
          {
              "repository":"repo3",
              "commit_nr":"3",
              /* ... */
          }
      ]
  }
4

3 回答 3

2

您想为此使用 perl:

$echo "          {
              "repository":"repo2",
              "commit_nr":"3",
              /* ... */
          }
      ]
  }
  {
      "commits":[
          {
              "repository":"repo3",
              "commit_nr":"1",
              /* ... */
          }," | perl -pn -e "BEGIN{undef $/;} s/\}\s*\]\s*\}\s*\{\s*commits:\[/},/g"

产量

          {
              repository:repo2,
              commit_nr:3,
              /* ... */
          },
          {
              repository:repo3,
              commit_nr:1,
              /* ... */
          },

注意:您可能需要在单词\"周围添加(这是一个,消失,因为它们没有被我的复制粘贴转义)commitecho"

于 2013-03-15T19:55:44.357 回答
0

听起来您想要的是 perl 中的触发器运算符,但由于您拥有(从我可以从您当前的输出中收集到的)是一堆格式良好的 perl 哈希,您可以通过组合旧哈希创建一个新哈希任何你喜欢的结构。然后,此 perl 脚本可以位于管道的末端并处理数据。

于 2013-03-15T19:56:40.927 回答
0

如果您只想使用 sed,则以下内容适用于您的示例输入:

sed -En '1h;1!H;${;g;s/( +)}\n +\]\n + }\n +{\n + "commits":\[\n/\1};/g;p;}'
于 2013-03-15T20:06:28.890 回答