用bash替换多行模式

时间:2013-03-15 19:46:05

标签: bash replace

我想替换它:

          }
      ]
  }
  {
      "commits":[

使用:

          },

使用bash 中提供的任何命令。

上面的文字正在解析from within the bash script itself(不是来自文件)。 “输入”是由4个不同的管道命令解析的git log的内容,它们将输出咀嚼并吐出到文件中。管道看起来像这样:

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

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

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

换句话说,我还没能找到合适的replace-multiline命令。也许你可以帮帮我? ;)

我尝试了什么

我在awksedgrep甚至是perl上使用了三天尝试不同的旋转(声称可以解决多线搜索和替换的问题)挑战)。他们都没有在我的背景下工作。我并不精通任何这些命令,所以我一直在黑暗中激励。 我真的很感激任何指针!

  背景      

我正在使用bash脚本将git log输出到有效JSON输出(project at github)。当脚本从存储库的根目录运行时,它工作得很好,但是我想扩展它以便它从包含所有存储库的目录运行,因此为{{{{}输出所有存储库的git log 1}}格式一次调用。

     

脚本被移动到父目录并在每个子目录(JSON repos)上运行,返回下面的输出(脚本也用于输出存储库名称作为属性每个对象项目。)

当前输出:

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",
              /* ... */
          }
      ]
  }

3 个答案:

答案 0 :(得分: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,
              /* ... */
          },

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

sed -En '1h;1!H;${;g;s/( +)}\n +\]\n + }\n +{\n + "commits":\[\n/\1};/g;p;}'