Linux 在同一行的两个位置使用sed或awk从多行中删除模式
我有一个包含12166466行的JSON文件。 我想从键上的值中删除引号:Linux 在同一行的两个位置使用sed或awk从多行中删除模式,linux,bash,awk,sed,jq,Linux,Bash,Awk,Sed,Jq,我有一个包含12166466行的JSON文件。 我想从键上的值中删除引号: “时间戳”:“1538564256”、和“分数”:“10”、看起来像 “时间戳”:1538564256,和“分数”:10, 输入: { "title": "DNS domain", , "timestamp": "1538564256", "domain": { "dns": [ "www.google.com" ] }, "
“时间戳”:“1538564256”、
和“分数”:“10”、
看起来像
“时间戳”:1538564256,
和“分数”:10,
输入:
{
"title": "DNS domain", ,
"timestamp": "1538564256",
"domain": {
"dns": [
"www.google.com"
]
},
"score": "10",
"link": "www.bit.ky/sdasd/asddsa"
"id": "c-1eOWYB9XD0VZRJuWL6"
}, {
"title": "DNS domain",
"timestamp": "1538564256",
"domain": {
"dns": [
"google.de"
]
},
"score": "10",
"link": "www.bit.ky/sdasd/asddsa",
"id": "du1eOWYB9XD0VZRJuWL6"
}
}
预期产出:
{
"title": "DNS domain", ,
"timestamp": 1538564256,
"domain": {
"dns": [
"www.google.com"
]
},
"score": 10,
"link": "www.bit.ky/sdasd/asddsa"
"id": "c-1eOWYB9XD0VZRJuWL6"
}, {
"title": "DNS domain",
"timestamp": 1538564256,
"domain": {
"dns": [
"google.de"
]
},
**"score": 10,**
"link": "www.bit.ky/sdasd/asddsa",
"id": "du1eOWYB9XD0VZRJuWL6"
}
}
我试过:
sed -E '
s/"timestamp": "/"timestamp": /g
s/"score": "/"score": /g
'
第一部分非常简单,但是如何删除“timestamp”和“score”行末尾的“?我如何使用sed、甚至awk或其他工具访问它,并记住我有1200万行要处理?如果JSON结构与您的示例大致匹配(例如,
“timestamp”
、冒号和值之间不会有任何其他空白字符),那么这个awk应该是可以的。如果可用,使用jq
进行JSON转换是目前最好的选择
awk '{print gensub(/("(timestamp|score)": )"([0-9]+)"/, "\\1\\3", "g")}' file
如果JSON结构与您的示例大致匹配(例如,
“timestamp”
、冒号和值之间不会有任何其他空格字符),那么这个awk应该是可以的。如果可用,使用jq
进行JSON转换是目前为止更好的选择
awk '{print gensub(/("(timestamp|score)": )"([0-9]+)"/, "\\1\\3", "g")}' file
假设您按照以下方式修复JSON输入文件:
<file jq .
[
{
"title": "DNS domain",
"timestamp": "1538564256",
"domain": {
"dns": [
"www.google.com"
]
},
"score": "10",
"link": "www.bit.ky/sdasd/asddsa",
"id": "c-1eOWYB9XD0VZRJuWL6"
},
{
"title": "DNS domain",
"timestamp": "1538564256",
"domain": {
"dns": [
"google.de"
]
},
"score": "10",
"link": "www.bit.ky/sdasd/asddsa",
"id": "du1eOWYB9XD0VZRJuWL6"
}
]
假设您按照以下方式修复JSON输入文件:
<file jq .
[
{
"title": "DNS domain",
"timestamp": "1538564256",
"domain": {
"dns": [
"www.google.com"
]
},
"score": "10",
"link": "www.bit.ky/sdasd/asddsa",
"id": "c-1eOWYB9XD0VZRJuWL6"
},
{
"title": "DNS domain",
"timestamp": "1538564256",
"domain": {
"dns": [
"google.de"
]
},
"score": "10",
"link": "www.bit.ky/sdasd/asddsa",
"id": "du1eOWYB9XD0VZRJuWL6"
}
]
tonumber
可能会失去精度。如果使用tonumber
是不允许的,并且如果输出是由jq生成的(或以其他方式垂直线性化),则按照本页其他地方的建议使用awk是一个很好的方法。(如果您的awk没有gensub,则可以轻松调整awk程序。)这里使用sed
,假设扩展正则表达式处理的标志是-E
,也是一样的:
sed-E-E's/“(时间戳|分数)”:“([0-9]+)”/“\1:\2/”
walk(如果类型==“对象”
如果有(“timestamp”),则.timestamp |=tonumber else.end
|如果有(“分数”),则.score |=tonumber else end
else.end)
walk/1
,则只需从web(例如从
walk(如果type==“object”,则映射值(tonumber?/)else.end)
tonumber
可能会失去精度。如果使用tonumber
是不允许的,并且如果输出是由jq生成的(或以其他方式垂直线性化),则按照本页其他地方的建议使用awk是一个很好的方法。(如果您的awk没有gensub,则可以轻松调整awk程序。)这里使用sed
,假设扩展正则表达式处理的标志是-E
,也是一样的:
sed-E-E's/“(时间戳|分数)”:“([0-9]+)”/“\1:\2/”
walk(如果类型==“对象”
如果有(“timestamp”),则.timestamp |=tonumber else.end
|如果有(“分数”),则.score |=tonumber else end
else.end)
walk/1
,则只需从web(例如从
walk(如果type==“object”,则映射值(tonumber?/)else.end)
”
。然后继续阅读,直到另一行包含时间戳并重复,或者一行包含“分数”:“10
并删除第三行或更多的”
。这可能适合您(GNU-sed):
遇到包含时间戳的行时:“1538564256”
删除第三行或更多”
。然后继续阅读,直到另一行包含时间戳并重复,或一行包含“score”:“10
并删除第三行或更多"
。没有使用sed或awk自己解析它,而是有一些JSON解析工具可以使用吗?JSON本身是使用JQ生成的。我相信没有办法告诉JQ不要对某些字段使用双引号。那怎么办?我会看看这个命令,我不知道它。我不会尝试类似的东西:sed-E's/:“([0-9]+)”/:\1/'file
没有使用sed或awk自己解析它,你可能会使用一些JSON解析工具吗?JSON本身是使用JQ生成的。我相信没有办法告诉JQ不要对某些字段使用双引号。那怎么办?我会看看这个命令,我不知道它。我不会尝试这样的事情: sed-e的/:“([0-9]+)”/:\1/”文件
我想你的意思是:awk'{print gensub(/“(timestamp | score)”:“([0-9]+)”/,“\“\\1\”:\\2”,“g”)}
@peak哦,是的,我错过了timestamp | score
周围的括号,谢谢!但我觉得直接否决有点苛刻:-(因为OP说JSON来自jq,我相信在这种情况下,用一个小的awk程序解析可以100%准确。如果你能准确地重新编写警告,我将向上投票:-)@peak好吧,看看JSON,它实际上在语法上是不正确的;-)(至少有三个错误)我想你的意思是:awk'{print gensub(/)(timestamp | score)“:”([0-9]+)“/,“\“\\1\”:\\2”,“g”)}
@peak哦,是的,我错过了timestamp | score
,谢谢!但我发现直接下推有点苛刻:-(因为OP说JSON来自jq,我相信在这种情况下,用一个小awk程序解析可以100%准确)。