JQ 从编码字段中替换“\n”
JQ replace "\n" from inside an encoded field
我现在已经尝试了很多解决方案,但我对JQ的理解有点欠缺,我是从2天前开始尝试使用它的。
我得到了一个非常好的解决方案来将我的文件从 Json 解析为 Csv,但有 1 个小陷阱。
Json 内部有 1 个 base64 编码的字段 (.data),它本身就是一个编码的 Json。在这个 sub-Json 中,有一个带有文本 (.text) 的字段,其中包含“\n”,并且在转换时,行被破坏,因为“\n”被转换为实际的换行符最终文件。
这是我现在的命令:
jq-linux64 -r '["ackId","data","senderPhoneNumber","eventType","eventId","messageId2","postbackData","text","sendTime","project_number","type","event_type","product","messageId","publishTime"], (.receivedMessages[] | [.ackId, .message.data, (.message.data | @base64d | fromjson | .senderPhoneNumber, .eventType, .eventId, .messageId, .postbackData, .text, .sendTime), .message.attributes.project_number, .message.attributes.type, .message.attributes.event_type, .message.attributes.product, .message.messageId,.message.publishTime]) | @csv' <inputfile.txt >outputfile.txt
在这个命令中,我进行解码,使用“fromjson”,然后从其中获取我需要的字段。
字段“.text”是我希望有换行符的字段 removed/replaced。
我尝试了 sub 和 gsub,但无法创建有效的命令行或产生所需输出的命令行。
关于如何从字段“,text”中替换“\n”的任何提示?
示例输入文件:
{
"receivedMessages": [
{
"ackId": "xxxxxx",
"message": {
"data": "eyJzZW5kZXJQaG9uZU51bWJlciI6ICIrOTk5OTk5OTk5OTk5OSIsIm1lc3NhZ2VJZCI6ICIyM2QyM2QyM2QzMmQiLCJzZW5kVGltZSI6ICIyMDIxLTAyLTAyVDIwOjAwOjAwLjAwMDAxIiwidGV4dCI6ICJYWFhYWCBYWFhYWFhYRSwgWFhYWFhYWC8gWHh4eHh4LlxuXG5YeHh4eHh4eHg6XG5cbjEgeHh4eCB4eCB4eHh4ICgyMDAgeHgpXG4yLDUgeHh4eHhcbjEgeHh4eCBcblxuWHh4eHh4IHh4eHh4eCJ9Cg==",
"attributes": {
"product": "XXXX",
"project_number": "XXXXXX",
"message_type": "TEXT",
"type": "message"
},
"messageId": "234234234234234234",
"publishTime": "2021-02-02T20:15:22.888Z"
}
}
]
}
当我用上面的命令处理这个文件时,它给出:
"ackId","data","senderPhoneNumber","eventType","eventId","messageId2","postbackData","text","sendTime","project_number","type","event_type","product","messageId","publishTime"
"xxxxxx","eyJzZW5kZXJQaG9uZU51bWJlciI6ICIrOTk5OTk5OTk5OTk5OSIsIm1lc3NhZ2VJZCI6ICIyM2QyM2QyM2QzMmQiLCJzZW5kVGltZSI6ICIyMDIxLTAyLTAyVDIwOjAwOjAwLjAwMDAxIiwidGV4dCI6ICJYWFhYWCBYWFhYWFhYRSwgWFhYWFhYWC8gWHh4eHh4LlxuXG5YeHh4eHh4eHg6XG5cbjEgeHh4eCB4eCB4eHh4ICgyMDAgeHgpXG4yLDUgeHh4eHhcbjEgeHh4eCBcblxuWHh4eHh4IHh4eHh4eCJ9Cg==","+9999999999999",,,"23d23d23d32d",,"XXXXX XXXXXXXE, XXXXXXX/ Xxxxxx.
Xxxxxxxxx:
1 xxxx xx xxxx (200 xx)
2,5 xxxxx
1 xxxx
Xxxxxx xxxxxx","2021-02-02T20:00:00.00001","XXXXXX","message",,"XXXX","234234234234234234","2021-02-02T20:15:22.888Z"
字段“.text”从编码的“\n”生成换行符,使 1 行变成多行,从而破坏该行以供后续处理。
---@peak
回答的完整答案代码
jq-linux64 -r '["ackId","data","senderPhoneNumber","eventType","eventId","messageId2","postbackData","text","sendTime","project_number","type","event_type","product","messageId","publishTime"], (.receivedMessages[] | [.ackId, .message.data, (.message.data|@base64d|fromjson|.senderPhoneNumber,.eventType,.eventId,.messageId,.postbackData,(.text | tostring | gsub("\n"; "|")),.sendTime),.message.attributes.project_number,.message.attributes.type,.message.attributes.event_type,.message.attributes.product,.message.messageId,.message.publishTime]) | @csv' <input.json >output.csv
将 -r 选项与 @csv
过滤器一起使用旨在(实际上在这种情况下)根据各种 CSV 标准生成有效的 CSV,这些标准允许在引用的字符串值中嵌入换行符。
因此,您似乎面临的问题是您用来提取 CSV 的程序不接受双引号字段中嵌入的换行符。
因此,最简单的解决方法可能是以您和其他程序都能接受的方式“编码”换行符。
例如,您可以使用 jq 过滤器将换行符编码为竖线(“|”)符号:
gsub("\n"; "|")
假设“文本”是一个可能包含嵌入换行符的字符串值字段,您可以将 .text
替换为
(.text | gsub("\n"; "|"))
如果 .text
的值可能为 null,那么您将必须决定要如何处理 null。 (一种可能性是:.text | tostring | gsub("\n";"|")
。)
如果您希望将转换应用于所有字符串字段,请将 | @csv
替换为类似以下内容:
| map(if type == "string" then gsub("\n"; "|") else . end)
| @csv
https://www.rfc-editor.org/rfc/rfc4180
Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes.
我现在已经尝试了很多解决方案,但我对JQ的理解有点欠缺,我是从2天前开始尝试使用它的。
我得到了一个非常好的解决方案来将我的文件从 Json 解析为 Csv,但有 1 个小陷阱。
Json 内部有 1 个 base64 编码的字段 (.data),它本身就是一个编码的 Json。在这个 sub-Json 中,有一个带有文本 (.text) 的字段,其中包含“\n”,并且在转换时,行被破坏,因为“\n”被转换为实际的换行符最终文件。
这是我现在的命令:
jq-linux64 -r '["ackId","data","senderPhoneNumber","eventType","eventId","messageId2","postbackData","text","sendTime","project_number","type","event_type","product","messageId","publishTime"], (.receivedMessages[] | [.ackId, .message.data, (.message.data | @base64d | fromjson | .senderPhoneNumber, .eventType, .eventId, .messageId, .postbackData, .text, .sendTime), .message.attributes.project_number, .message.attributes.type, .message.attributes.event_type, .message.attributes.product, .message.messageId,.message.publishTime]) | @csv' <inputfile.txt >outputfile.txt
在这个命令中,我进行解码,使用“fromjson”,然后从其中获取我需要的字段。
字段“.text”是我希望有换行符的字段 removed/replaced。
我尝试了 sub 和 gsub,但无法创建有效的命令行或产生所需输出的命令行。
关于如何从字段“,text”中替换“\n”的任何提示?
示例输入文件:
{
"receivedMessages": [
{
"ackId": "xxxxxx",
"message": {
"data": "eyJzZW5kZXJQaG9uZU51bWJlciI6ICIrOTk5OTk5OTk5OTk5OSIsIm1lc3NhZ2VJZCI6ICIyM2QyM2QyM2QzMmQiLCJzZW5kVGltZSI6ICIyMDIxLTAyLTAyVDIwOjAwOjAwLjAwMDAxIiwidGV4dCI6ICJYWFhYWCBYWFhYWFhYRSwgWFhYWFhYWC8gWHh4eHh4LlxuXG5YeHh4eHh4eHg6XG5cbjEgeHh4eCB4eCB4eHh4ICgyMDAgeHgpXG4yLDUgeHh4eHhcbjEgeHh4eCBcblxuWHh4eHh4IHh4eHh4eCJ9Cg==",
"attributes": {
"product": "XXXX",
"project_number": "XXXXXX",
"message_type": "TEXT",
"type": "message"
},
"messageId": "234234234234234234",
"publishTime": "2021-02-02T20:15:22.888Z"
}
}
]
}
当我用上面的命令处理这个文件时,它给出:
"ackId","data","senderPhoneNumber","eventType","eventId","messageId2","postbackData","text","sendTime","project_number","type","event_type","product","messageId","publishTime"
"xxxxxx","eyJzZW5kZXJQaG9uZU51bWJlciI6ICIrOTk5OTk5OTk5OTk5OSIsIm1lc3NhZ2VJZCI6ICIyM2QyM2QyM2QzMmQiLCJzZW5kVGltZSI6ICIyMDIxLTAyLTAyVDIwOjAwOjAwLjAwMDAxIiwidGV4dCI6ICJYWFhYWCBYWFhYWFhYRSwgWFhYWFhYWC8gWHh4eHh4LlxuXG5YeHh4eHh4eHg6XG5cbjEgeHh4eCB4eCB4eHh4ICgyMDAgeHgpXG4yLDUgeHh4eHhcbjEgeHh4eCBcblxuWHh4eHh4IHh4eHh4eCJ9Cg==","+9999999999999",,,"23d23d23d32d",,"XXXXX XXXXXXXE, XXXXXXX/ Xxxxxx.
Xxxxxxxxx:
1 xxxx xx xxxx (200 xx)
2,5 xxxxx
1 xxxx
Xxxxxx xxxxxx","2021-02-02T20:00:00.00001","XXXXXX","message",,"XXXX","234234234234234234","2021-02-02T20:15:22.888Z"
字段“.text”从编码的“\n”生成换行符,使 1 行变成多行,从而破坏该行以供后续处理。
---@peak
回答的完整答案代码jq-linux64 -r '["ackId","data","senderPhoneNumber","eventType","eventId","messageId2","postbackData","text","sendTime","project_number","type","event_type","product","messageId","publishTime"], (.receivedMessages[] | [.ackId, .message.data, (.message.data|@base64d|fromjson|.senderPhoneNumber,.eventType,.eventId,.messageId,.postbackData,(.text | tostring | gsub("\n"; "|")),.sendTime),.message.attributes.project_number,.message.attributes.type,.message.attributes.event_type,.message.attributes.product,.message.messageId,.message.publishTime]) | @csv' <input.json >output.csv
将 -r 选项与 @csv
过滤器一起使用旨在(实际上在这种情况下)根据各种 CSV 标准生成有效的 CSV,这些标准允许在引用的字符串值中嵌入换行符。
因此,您似乎面临的问题是您用来提取 CSV 的程序不接受双引号字段中嵌入的换行符。
因此,最简单的解决方法可能是以您和其他程序都能接受的方式“编码”换行符。
例如,您可以使用 jq 过滤器将换行符编码为竖线(“|”)符号:
gsub("\n"; "|")
假设“文本”是一个可能包含嵌入换行符的字符串值字段,您可以将 .text
替换为
(.text | gsub("\n"; "|"))
如果 .text
的值可能为 null,那么您将必须决定要如何处理 null。 (一种可能性是:.text | tostring | gsub("\n";"|")
。)
如果您希望将转换应用于所有字符串字段,请将 | @csv
替换为类似以下内容:
| map(if type == "string" then gsub("\n"; "|") else . end)
| @csv
https://www.rfc-editor.org/rfc/rfc4180
Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes.