【问题标题】:sed replace between 2 patterns of JSON file that have multi occurrencessed 在具有多次出现的 JSON 文件的 2 种模式之间替换
【发布时间】:2021-06-07 16:19:55
【问题描述】:

我需要替换 JSON 文件的 2 种模式之间的任何表达式,这些模式多次出现,我只想根据自己的选择替换它们一次(假设在 6 次中的第 4 次出现)。

我创建了一个 sed 表达式,当我在文件中只有一次出现时,它可以工作, 但是当添加多个时,由于某种原因在尝试替换第二个匹配项时不起作用。

这是我的 sed:

images_one_line=MAMA

sed -i 's/CDATA\[.*\]\]>/CDATA[ '"${images_one_line}"' ]]>/2' response.json

这是 response.json 文件:

{"id":"1929905018","type":"page","status":"current","title":"CODEFRESH-CHANGE-API","version":{"by":{"type":"known","accountId":"6066297300b79f0070e308cb","accountType":"atlassian","email":"shachar.rajuan@veeva.com","publicName":"shachar.rajuan","profilePicture":{"path":"/wiki/aa-avatar/6066297300b79f0070e308cb","width":48,"height":48,"isDefault":false},"displayName":"Shachar Rajuan","isExternalCollaborator":false,"_expandable":{"operations":"","personalSpace":""},"_links":{"self":"https://crossixsolutions.atlassian.net/wiki/rest/api/user?accountId=6066297300b79f0070e308cb"}},"when":"2021-06-07T16:00:41.499Z","friendlyWhen":"less than a minute ago","message":"","number":128,"minorEdit":false,"syncRev":"4.confluence$content$1929905018.362","syncRevSource":"synchrony-ack","confRev":"confluence$content$1929905018.363","contentTypeModified":false,"_expandable":{"collaborators":"","content":"/rest/api/content/1929905018"},"_links":{"self":"https://crossixsolutions.atlassian.net/wiki/rest/api/content/1929905018/version/128"}},"macroRenderedOutput":{},"body":{"storage":{"value":"<p /><table data-layout=\"default\"><colgroup><col style=\"width: 70.0px;\" /><col style=\"width: 65.0px;\" /><col style=\"width: 222.0px;\" /><col style=\"width: 48.0px;\" /><col style=\"width: 70.0px;\" /><col style=\"width: 48.0px;\" /><col style=\"width: 65.0px;\" /><col style=\"width: 76.0px;\" /><col style=\"width: 96.0px;\" /></colgroup><tbody><tr><th><p><strong>Environment</strong></p></th><th><p><strong>Data Loaded</strong></p></th><th><p><strong>version/branch</strong></p></th><th><p><strong>Owner</strong></p></th><th><p><strong>Used for</strong></p></th><th colspan=\"3\"><p style=\"text-align: center;\"><strong>Cluster size</strong></p></th><th><p><strong>env prefix</strong></p></th></tr><tr><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p><strong>Size</strong></p></td><td data-highlight-colour=\"#f4f5f7\"><p><strong>ES - nodes</strong></p></td><td data-highlight-colour=\"#f4f5f7\"><p><strong>Mongo - Shards</strong></p></td><td data-highlight-colour=\"#f4f5f7\"><p /></td></tr><tr><td><p><span style=\"color: rgb(76,154,255);\">cds-dev-1</span></p></td><td><p>10 node, 1 day,  33 files </p></td><td><ac:structured-macro ac:name=\"warning\" ac:schema-version=\"1\" ac:macro-id=\"20ce769a-0655-4cb5-92ae-8238e47d6729\"><ac:rich-text-body><p>This field is being updated automatically using CodeFresh Build.<br />Do not change it manually! </p></ac:rich-text-body></ac:structured-macro><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"c16e8ce6-aad5-4778-a2f4-eaff5bc3a0f5\"><ac:parameter ac:name=\"language\">bash</ac:parameter><ac:plain-text-body><![CDATA[ \ncds-feeder-srv\n  newTag: devleap \ncds-shard-es-srv\n  newTag: master_fuffffffu \ncds-loader-srv\n  newTag: shahar-pip2  ]]></ac:plain-text-body></ac:structured-macro><p /></td><td><p>DEV/Atara</p></td><td><p>functional tests</p></td><td><p>tiny</p></td><td><p>2 nodes</p></td><td><p>3 shards, M40</p></td><td><p /></td></tr><tr><td><p><span style=\"color: rgb(76,154,255);\">cds-dev-2</span></p></td><td><p>1 node</p></td><td><ac:structured-macro ac:name=\"warning\" ac:schema-version=\"1\" ac:macro-id=\"e233aff4-ae50-4c86-a7c2-188d9b2c03e6\"><ac:rich-text-body><p>This field is being updated automatically using CodeFresh Build.<br />Do not change it manually! </p></ac:rich-text-body></ac:structured-macro><p /><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"985a38af-9f30-4329-a763-368a0ebb3984\"><ac:parameter ac:name=\"language\">bash</ac:parameter><ac:plain-text-body><![CDATA[ cds-feeder-srv\n  newTag: testing ]]></ac:plain-text-body></ac:structured-macro></td><td><p>shalom</p></td><td><p>shalom</p></td><td><p>small</p></td><td><p>1 node</p></td><td><p>1 shard</p></td><td><p /></td></tr></tbody></table><p />","representation":"storage","embeddedContent":[],"_expandable":{"content":"/rest/api/content/1929905018"}},"_expandable":{"editor":"","atlas_doc_format":"","view":"","export_view":"","styled_view":"","dynamic":"","editor2":"","anonymous_export_view":""}},"extensions":{"position":363304566},"_expandable":{"childTypes":"","container":"/rest/api/space/SD","metadata":"","operations":"","schedulePublishDate":"","children":"/rest/api/content/1929905018/child","restrictions":"/rest/api/content/1929905018/restriction/byOperation","history":"/rest/api/content/1929905018/history","ancestors":"","descendants":"/rest/api/content/1929905018/descendant","space":"/rest/api/space/SD"},"_links":{"editui":"/pages/resumedraft.action?draftId=1929905018","webui":"/spaces/SD/pages/1929905018/CODEFRESH-CHANGE-API","context":"/wiki","self":"https://crossixsolutions.atlassian.net/wiki/rest/api/content/1929905018","tinyui":"/x/egMIcw","collection":"/rest/api/content","base":"https://crossixsolutions.atlassian.net/wiki"}}

我的 sed 正在做的是替换 CDATA[]] 之间的所有内容, 使用全局选项/g 时我得到的是:

{"id":"1929905018","type":"page","status":"current","title":"CODEFRESH-CHANGE-API","version":{"by":{"type":"known","accountId":"6066297300b79f0070e308cb","accountType":"atlassian","email":"shachar.rajuan@veeva.com","publicName":"shachar.rajuan","profilePicture":{"path":"/wiki/aa-avatar/6066297300b79f0070e308cb","width":48,"height":48,"isDefault":false},"displayName":"Shachar Rajuan","isExternalCollaborator":false,"_expandable":{"operations":"","personalSpace":""},"_links":{"self":"https://crossixsolutions.atlassian.net/wiki/rest/api/user?accountId=6066297300b79f0070e308cb"}},"when":"2021-06-07T16:14:01.265Z","friendlyWhen":"less than a minute ago","message":"Reverted from v. 134","number":136,"minorEdit":false,"syncRev":"4.confluence$content$1929905018.377","syncRevSource":"synchrony-ack","confRev":"confluence$content$1929905018.379","contentTypeModified":false,"_expandable":{"collaborators":"","content":"/rest/api/content/1929905018"},"_links":{"self":"https://crossixsolutions.atlassian.net/wiki/rest/api/content/1929905018/version/136"}},"macroRenderedOutput":{},"body":{"storage":{"value":"<p /><table data-layout=\"default\"><colgroup><col style=\"width: 70.0px;\" /><col style=\"width: 65.0px;\" /><col style=\"width: 222.0px;\" /><col style=\"width: 48.0px;\" /><col style=\"width: 70.0px;\" /><col style=\"width: 48.0px;\" /><col style=\"width: 65.0px;\" /><col style=\"width: 76.0px;\" /><col style=\"width: 96.0px;\" /></colgroup><tbody><tr><th><p><strong>Environment</strong></p></th><th><p><strong>Data Loaded</strong></p></th><th><p><strong>version/branch</strong></p></th><th><p><strong>Owner</strong></p></th><th><p><strong>Used for</strong></p></th><th colspan=\"3\"><p style=\"text-align: center;\"><strong>Cluster size</strong></p></th><th><p><strong>env prefix</strong></p></th></tr><tr><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p /></td><td data-highlight-colour=\"#f4f5f7\"><p><strong>Size</strong></p></td><td data-highlight-colour=\"#f4f5f7\"><p><strong>ES - nodes</strong></p></td><td data-highlight-colour=\"#f4f5f7\"><p><strong>Mongo - Shards</strong></p></td><td data-highlight-colour=\"#f4f5f7\"><p /></td></tr><tr><td><p><span style=\"color: rgb(76,154,255);\">cds-dev-1</span></p></td><td><p>10 node, 1 day,  33 files </p></td><td><ac:structured-macro ac:name=\"warning\" ac:schema-version=\"1\" ac:macro-id=\"20ce769a-0655-4cb5-92ae-8238e47d6729\"><ac:rich-text-body><p>This field is being updated automatically using CodeFresh Build.<br />Do not change it manually! </p></ac:rich-text-body></ac:structured-macro><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"c16e8ce6-aad5-4778-a2f4-eaff5bc3a0f5\"><ac:parameter ac:name=\"language\">bash</ac:parameter><ac:plain-text-body><![CDATA[ cds-feeder-srv newTag: buba cds-shard-es-srv newTag: release3 cds-loader-srv newTag: pip6 ]]></ac:plain-text-body></ac:structured-macro></td><td><p>shalom</p></td><td><p>shalom</p></td><td><p>small</p></td><td><p>1 node</p></td><td><p>1 shard</p></td><td><p /></td></tr></tbody></table><p />","representation":"storage","embeddedContent":[],"_expandable":{"content":"/rest/api/content/1929905018"}},"_expandable":{"editor":"","atlas_doc_format":"","view":"","export_view":"","styled_view":"","dynamic":"","editor2":"","anonymous_export_view":""}},"extensions":{"position":363304566},"_expandable":{"childTypes":"","container":"/rest/api/space/SD","metadata":"","operations":"","schedulePublishDate":"","children":"/rest/api/content/1929905018/child","restrictions":"/rest/api/content/1929905018/restriction/byOperation","history":"/rest/api/content/1929905018/history","ancestors":"","descendants":"/rest/api/content/1929905018/descendant","space":"/rest/api/space/SD"},"_links":{"editui":"/pages/resumedraft.action?draftId=1929905018","webui":"/spaces/SD/pages/1929905018/CODEFRESH-CHANGE-API","context":"/wiki","self":"https://crossixsolutions.atlassian.net/wiki/rest/api/content/1929905018","tinyui":"/x/egMIcw","collection":"/rest/api/content","base":"https://crossixsolutions.atlassian.net/wiki"}}

当使用 \2 应该替换 s2d 事件时,我没有看到任何变化。

【问题讨论】:

  • 您能否确认jq 是否适合您?恕我直言,专家从不建议使用 sed 编辑 json 文件,始终建议使用能够很好理解 json 的工具编辑 json 文件(不是我的反对票),谢谢。
  • .* 更改为[^]]*

标签: bash shell sed


【解决方案1】:

这在一行中接近 5 KiB 的 JSON — 尝试阅读它很痛苦。

[CDATA[…]] 有两个序列——第一个大约 140 个字符长,第二个大约 45 个字符长。您的主要问题是 .* 脚本中的 sed 符号是“贪婪的”;它将在第一个 CDATA 之后开始匹配并读取到第二个结束。您需要限制它,使其不会跳过 ]] 结束标记。这不是微不足道的。一个适度的近似是:

sed -e 's/CDATA\[[^]]*\]\]>/CDATA[ '"${images_one_line}"' ]]>/' response.json

这不会在CDATA 标记之前捕获![[;这大概没关系。

然后,您可以使用 GNU sed 扩展来选择要更改的行上出现的 CDATA — 在 s/// 命令的关闭 / 之后添加一个合适的数字。

请注意,如果 CDATA 中的数据包含任何右方括号,您仍然可能会遇到麻烦。

此版本使用sed“扩展正则表达式”或 ERE 支持。这通常由-E 启用,但GNU sed 也可以识别-r

sed -E -e 's/<!\[CDATA\[([^]]*|\][^]])*\]\]>/<![CDATA[ substituted ]]>/g' response.json

与 Perl 兼容的正则表达式会更好——但仍然很重要。这个 Perl 脚本显示了一个工作版本:

#!/usr/bin/env perl

use strict;
use warnings;

while (<>)
{
    s/<!\[CDATA\[(?:[^]]*|\][^]])*\]\]>/<![CDATA[ substituted ]]>/g;
    print;
}

像这样编辑 JSON 数据是有问题的,正如 cmets 中所指出的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    相关资源
    最近更新 更多