【问题标题】:Feeding sed matched block through a command通过命令提供 sed 匹配的块
【发布时间】:2015-07-03 02:19:48
【问题描述】:

我有每行包含多个部分的 json 行,如下所示:

"SomeDate":"Date(-2156284800000)",

我想将所有行中的每次出现都转换为更易于阅读的内容:

"SomeDate":"1901-09-03 00:19:32",

我尝试使用 sed 将匹配的块(在本例中为时间戳)放入 date 命令的参数列表中。这失败了。

$ echo '"SomeDate":"Date(-2156284800000)",' | \
  sed "s/Date(\([0-9\-]*\)[0-9][0-9][0-9])/$(date -d@\\1 \"+%F %T\")/g"

date: invalid date `@\\1'
"SomeDate":"",

为了调试这一切,我在日期中添加了一个“echo”以验证它应该运行的命令

$ echo '"SomeDate":"Date(-2156284800000)",' | \
  sed "s/Date(\([0-9\-]*\)[0-9][0-9][0-9])/$(echo date -d@\\1 \"+%F %T\")/g"

"SomeDate":"date -d@-2156284800 "+%F %T"",


$ date -d@-2156284800 "+%F %T"

1901-09-03-00:19:32

为什么第一个命令没有按预期运行?

我现在最好的猜测是,首先执行子shell而不用\1替换,然后sed实际使用结果输出。

我如何实现我想要做的事情?

附:我正在使用 CentOS 6.6

【问题讨论】:

  • 请注意,您正在打开一个子shell 来执行命令,因此该值可能不会“到达”那里。此外,要在sed 中执行命令,您需要/e
  • 如果您将\\1 替换为-2156284800,您将看到它可以工作,这表明\\1 与之前的字符串不匹配,原因由@fedorqui 描述。 Fedorqui,你不需要/e,因为这对我有用?
  • 我尝试了 gnu sed 的 'e' 选项。 echo "bla foo bla foo" | sed -e "s@(foo)@echo XX\1XX@e" 期望输出:bla XXfooXX bla XXfooXX 实际输出:sh: bla: command not found
  • 使用适当的 JSON 解析器用一种语言编写脚本会容易得多。

标签: regex bash sed subshell


【解决方案1】:

使用awk怎么样:

echo '"SomeDate":"Date(-2156284800000)",' | awk '{ print gensub(/Date\(([0-9\-]+)\)/, ("date -d@\\1 \"+%F %T\"" |& getline t) ? t : "\\1", "g"); }'

免责声明:可能有更好的方法来做到这一点,但简而言之:

  • gensub 类似于 gsub,但允许您访问匹配的组
  • 使用以下命令捕获 Date(XXX) 位:

    /Date\(([0-9\-]+)\)/
    

    (获取匹配组\1中的实际纪元)

  • 第二个参数是:

    ("date -d@\\1 \"+%F %T\"" |& getline t) ? t : "\\1"
    

    形成日期命令,运行它(使用getline)并将结果分配给变量tgetline,成功时奇怪地返回 1,因此我们使用三元 (?:) 语句检查它并返回该命令的第一行输出。

  • 最后,我们告诉gensub 是全局的。

【讨论】:

  • Awk 有一个已知错误,并为 1970 年之前的日期给出错误答案。您的脚本给出了 "SomeDate":"1970-01-01 01:00:01",
  • 哦,烦人。那么 perl 或将 awk 导入 shell 可能是最好的方法?
【解决方案2】:

我现在使用的解决方法是通过 perl:

$ echo fee 4321432431 fie 1429882795 fum | \
       perl -MPOSIX -pe 's/(\d+)/strftime "%F", localtime $1/eg'


fee 2106-12-10 fie 2015-04-24 fum

【讨论】:

    猜你喜欢
    • 2013-06-29
    • 2014-04-22
    • 2016-07-25
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多