bash - 用 sed 中命令的输出替换模式
问题描述
假设我有一些文本文件(在这种情况下为 json):
{
"data": [
{
"timestamp": 1577856103107
},
{
"timestamp": 1577869991302
}
]
}
我想用更易读的日期格式替换一个模式(在本例中为 UNIX 毫秒时间戳)。
我正在尝试这个:
$ sed -E 's/(.*)([0-9]{13})/echo "\1\\"$(date --date="@$((\2\/1000))" --iso-8601=seconds)\\""/e' example.json
{
"data": [
{
timestamp: "2020-01-01T00:21:43-05:00"
},
{
timestamp: "2020-01-01T04:13:11-05:00"
}
]
}
这有点好,但我不明白为什么周围的引号timestamp
会丢失。
此命令有效:
sed -E 's/(.*)"(timestamp)"(: )([0-9]{13})/echo "\1\\"\2\\"\3\\"$(date --date="@$((\4\/1000))" --iso-8601=seconds)"\\"/e' example.json
{
"data": [
{
"timestamp": "2020-01-01T00:21:43-05:00"
},
{
"timestamp": "2020-01-01T04:13:11-05:00"
}
]
}
我也不明白为什么我需要双反斜杠来在这个 sed 命令的右侧\\
输出双引号。"
有没有更好的方法(或工具)来解决这个问题?
我在sed (GNU sed) 4.8
,zsh 5.8 (x86_64-pc-linux-gnu)
谢谢!
解决方案
有没有更好的方法(或工具)来解决这个问题?
用于操作jsonsed
的东西非常粗糙。您无法使用正则表达式解析 json。我(强烈)建议使用 json 感知工具,例如jq
.
jq '.data[].timestamp |= (. / 1000 | strftime("%Y-%m-%dT%H:%M:%SZ"))'
但我不明白为什么时间戳周围的引号会丢失。
这:
echo "\1\\"$(date --date="@$((\2\/1000))" --iso-8601=seconds)\\""
被“取代”为:
echo ""timestamp": \"$(date --date="@$((1577856103107/1000))" --iso-8601=seconds)\""
^^
^------------------------------------------------------------------^
然后传递给 shell 并根据 shell 规则重新评估引号。
匹配(.*)
真的是什么都不做,只匹配你想替换的部分。您可以改为仅匹配要替换的部分:
sed '/"timestamp":/s/([0-9]{13})/echo "\\"$(date --date="@$((\1\/1000))" --iso-8601=seconds)\\""/e'
为什么我需要双反斜杠 \ 在此 sed 命令的右侧输出双引号 "。
首先\\
被解释sed
为 single \
。
$ echo a | sed 's/.*/single slash: \\/'
single slash: \
然后将命令的结果sed
传递给 shell,所有的 shell 解析规则都会再次完成。
推荐阅读
- database - 如何在 BigQuery 中显示存储过程的定义?
- angular - 使用 Angular Pipes 将一位数变成两位数
- python - Python列表中的不同
- laravel - 重命名迁移文件夹中的文件后,Laravel 未迁移
- php - 您好,有人可以向我解释一下这个 php $_SESSION 脚本吗?
- windows - VirtualHost 不适用于 localhost WAMP 服务器中的“.com”域
- soapui - SoapUI:当我在 JDBC 请求中进行更新后进行选择时,我看不到选择结果
- asp.net-mvc - 从 Razor 调用控制器操作方法(ASP.NET MVC,.netcore 3.x/5.x)
- python - sudo pip list:OpenSSL 问题
- sql - MS-ACCESS,加入 SQL 选择