【问题标题】:Add an empty line prior to another matched line in jq?在 jq 中的另一个匹配行之前添加一个空行?
【发布时间】:2018-03-02 22:50:17
【问题描述】:

假设我有如下原始输入:

"```"
"include <stdio.h>"
"..."
"```"
"''some example''"
"*bob"
"**bob"
"*bob"

我想在 "*bob" 之前添加一个空行:

"```"
"include <stdio.h>"
"..."
"```"
"''some example''"
""
"*bob"
"**bob"
"*bob"

用jq可以做到吗?

【问题讨论】:

  • 使用 sed 更容易
  • 你为什么用jq?您正在处理数据字符串,其中可能甚至没有任何 json。有更好的工具。
  • @JeffMercado 因为我最终需要将其转换为 JSON 数据,而 jq 提供了漂亮的工具……现在也许它不是读取文件的最佳工具,但它非常适合输出 JSON。

标签: json stream edit jq


【解决方案1】:

这是另一个使用 -s (slurp) 选项的解决方案

.[: .[["*bob"]][0]] + ["\n"] + .[.[["*bob"]][0]:] | .[]        

这有点难以理解,但我们可以通过一些函数使它变得更好:

  def firstbob:  .[["*bob"]][0] ;
  def beforebob: .[: firstbob ] ;
  def afterbob:  .[ firstbob :] ;

    beforebob + ["\n"] + afterbob
  | .[]

如果上面的过滤器在filter.jq中并且样本数据在data那么

$ jq -Ms -f filter.jq data

生产

"```"
"include <stdio.h>"
"..."
"```"
"''some example''"
"\n"
"*bob"
"**bob"
"*bob"

这种方法的一个问题是,如果"*bob" 不在输入中,afterbobafterbob 可能无法正常工作。解决这个问题的最简单方法是使用 if 守卫:

    if firstbob then beforebob + ["\n"] + afterbob else . end
  | .[]

如果"*bob" 不存在,输入将保持不变。

【讨论】:

    【解决方案2】:

    是的,但要有效地做到这一点,您实际上需要 jq 1.5 或更高版本:

    foreach inputs as $line (0; 
      if $line == "*bob" then . + 1 else . end;
      if . == 1 then "" else empty end,
        $line)
    

    别忘了使用 -n 命令行选项!

    【讨论】:

      猜你喜欢
      • 2018-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多