{"id":635,"date":"2025-12-03T21:19:13","date_gmt":"2025-12-03T21:19:13","guid":{"rendered":"https:\/\/camilo.matajira.com\/?p=635"},"modified":"2025-12-03T21:20:15","modified_gmt":"2025-12-03T21:20:15","slug":"jed-the-loyal-json-successor-to-sed","status":"publish","type":"post","link":"https:\/\/camilo.matajira.com\/?p=635","title":{"rendered":"JED, the loyal json successor to SED"},"content":{"rendered":"\n<p>Lately, I have felt dissatisfied with jq for manipulating json in the command line and in scripts.<br>The personal reason, is that I like investing in tools that have withstood the test of time and I like learning them well.<\/p>\n\n\n\n<p>One example of these tools is vim. Learning vim has had a great payoff, and part of its charm is that, if I grow tired of it I can still transfer my knowledge of the vim key bindings to other tools or editors. I could move to Neovim, or if I&#8217;m more interested in writing text, I could use the key bindings in Obsidian. I have seen plugins for vim in VS Code, JetBrains, etcetera. And having studied vim, understanding a tool like grep is natural g\/re\/p (I do know that g\/re\/p comes from ex).<\/p>\n\n\n\n<p>My point is that learning vim has been a safe bet with high return. The same is true for sed and awk. Yet, here is jq, that claims to be a &#8220;jq is like sed for JSON data &#8211; you can use it to slice and filter and map and transform structured data with the same ease that sed, awk, grep and friends let you play with text.&#8221; But jq does not resemble anything of sed, awk or grep. I can&#8217;t transfer my knowledge of sed, awk or grep to jq.<\/p>\n\n\n\n<p>That why, I started working on JED (json sed). My objective is to create a json parsing tools that feels like home for sed power users. And if I do it correctly, the benefits would be evident: not because of the tools itself, but because sed is great.<\/p>\n\n\n\n<p>What I have in mind is something like this, let&#8217;s start with a simple json:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>{\n\"sha\": \"0eb3\",\n\"node_id\": \"OAE3WVd\",\n\"commit\": {\n  \"author\": {\n    \"name\": \"Camilo MATAJIRA\",\n    \"email\": \"ca.matajira966@gmail.com\",\n    \"date\": \"2025-11-27T09:44:45Z\"\n  },\n  \"committer\": {\n    \"name\": \"Camilo MATAJIRA\",\n    \"email\": \"fake_email@gmail.com\",\n    \"date\": \"2025-11-27T09:44:45Z\"\n  },<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">&quot;sha&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">0eb3<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">&quot;node_id&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">OAE3WVd<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">&quot;commit&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">  <\/span><span style=\"color: #50FA7B\">&quot;author&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">&quot;name&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">Camilo MATAJIRA<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">&quot;email&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">ca.matajira966@gmail.com<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">&quot;date&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">2025-11-27T09:44:45Z<\/span><span style=\"color: #E9F284\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">  },<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">  <\/span><span style=\"color: #50FA7B\">&quot;committer&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">&quot;name&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">Camilo MATAJIRA<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">&quot;email&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">fake_email@gmail.com<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">&quot;date&quot;<\/span><span style=\"color: #8BE9FD\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">2025-11-27T09:44:45Z<\/span><span style=\"color: #E9F284\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">  },<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Let say that I want to change &#8220;Camilo MATAJIRA&#8221; to &#8220;Camilo A. MATAJIRA&#8221;.<br>I could do that very easily with sed:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>sed 's\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">sed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Yet, what if I want to do this only on the &#8220;author&#8221; section and not in the committer?<br>With sed, I could do something like this:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>sed '\/\"author\"\/,\/}\\,\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">sed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/&quot;author&quot;\/,\/}\\,\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>I would profit from sed&#8217;s range feature, that allows me to specify a range of lines where the substitution would take place. It will work, but we start having the flavor that sed could profit from understanding the hierarchical nature of json.<\/p>\n\n\n\n<p>In jed I could do:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>jed '\/author\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/author\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This would read like &#8220;wherever you find a key, at any level of the tree hierarchy that satisfies the regex \/author\/, perform the following substitution.&#8221;<\/p>\n\n\n\n<p>This could also be written like:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>jed '\/commit\/.\/author\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/commit\/.\/author\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This would read &#8220;wherever you find a succession of keys at any level of the json, the first one should satisfy the regex \/commit\/, and the next one (the child) satisfies \/author\/, perform the following substitution there.&#8221;<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>jed '\/commit\/.\/author\/.\/name\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/commit\/.\/author\/.\/name\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This one would read like the previous one but adding the condition of the last key being &#8220;name&#8221;.<\/p>\n\n\n\n<p>It is important to note, that I said these all are regular expressions.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>jed '\/^comm.*\/.\/aut.*\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/^comm.*\/.\/aut.*\/ s\/Camilo MATAJIRA\/Camilo A. MATAJIRA\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This would work the same, but is very pleasant to be able to work with regexes, and not be tight to providing the exact succession of keys.<\/p>\n\n\n\n<p>Now, let&#8217;s say that I would like to change the key &#8220;name&#8221; to &#8220;author_name&#8221;, in other words I would like commit.author.name \u2192 commit.author.author_name.<br>I could do it in many ways:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>jed '\/author\/ S\/name\/author_name\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/author\/ S\/name\/author_name\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>First check that I use &#8220;S&#8221; instead of &#8220;s&#8221;, because we are substituting a key, not a value. This is a way of differentiation when the actions should operate on keys rather than values.<br>And this reads &#8220;where you find a key, at any level of the json, that satisfies \/author\/, perform the substitution of key name to author_name there.&#8221;<\/p>\n\n\n\n<p>But how about I want the values to be part of the regex conditions?<br>Let&#8217;s say that I want to change the key &#8220;email&#8221; to &#8220;committer_email&#8221; but only where the value of email is &#8220;fake_email@gmail.com&#8221;. Again, many ways to do it, but one way is:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>jed ':\/fake_email@gmail.com\/ S\/email\/commiter_mail\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">:\/fake_email@gmail.com\/ S\/email\/commiter_mail\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>See the &#8220;:&#8221; at the beginning? This indicates that the regex expression is applying to the values, not to the keys.<br>Other equivalent way to do it:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>jed '\/.*\/:\/fake_email@gmail.com\/ S\/email\/commiter_mail\/g' file.json\njed '\/.*\/.\/.*\/:\/fake_email@gmail.com\/ S\/email\/commiter_mail\/g' file.json\njed '\/.*\/.\/.*\/.\/.*\/:\/fake_email@gmail.com\/ S\/email\/commiter_mail\/g' file.json<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/.*\/:\/fake_email@gmail.com\/ S\/email\/commiter_mail\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/.*\/.\/.*\/:\/fake_email@gmail.com\/ S\/email\/commiter_mail\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">jed<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">\/.*\/.\/.*\/.\/.*\/:\/fake_email@gmail.com\/ S\/email\/commiter_mail\/g<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">file.json<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Similar operations would apply for deletion (d and D), appending (a and A), inserting (i and I), and changing (c and C).<\/p>\n\n\n\n<p>In conclusion, this is the project that I would like to create. I started working already on the DSL, I hope that it will be useful to you too.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lately, I have felt dissatisfied with jq for manipulating json in the command line and in scripts.The personal reason, is that I like investing in tools that have withstood the test of time and I like learning them well. One example of these tools is vim. Learning vim has had a great payoff, and part&#8230;<\/p>\n","protected":false},"author":1,"featured_media":356,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-635","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-projects"],"_links":{"self":[{"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/posts\/635","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=635"}],"version-history":[{"count":1,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/posts\/635\/revisions"}],"predecessor-version":[{"id":636,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/posts\/635\/revisions\/636"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/media\/356"}],"wp:attachment":[{"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}