Search code examples
regexbashawksed

Bash split JSON to blocks and replace string within each block


I have a JSON file with the following content:

{
    "Text %s and %s": "Text2 %s or %s",
    "Here is \"Name %s\" and %s and %s": "Blabla %s and %s or %s"
}

I need a bash command with use of some awk or sed converting this content to the following result:

{
    "Text %1$s and %2$s": "Text2 %1$s or %2$s",
    "Here is \"Name %1$s\" and %2$s and %3$s": "Blabla %1$s and %2$s or %3$s"
}

So i need to replace each %s with indexed copy within each qouted block. I tried some gpt generated code with no luck

awk -F'"' '                                                                                                         
  BEGIN { idx = 1 }
  {
    for (i=1; i<=NF; i++) {
      if (i % 2 == 0) {
        gsub(/%s/, "%" idx++ "$s", $i)
      }
    }
    idx = 1
  }
  1
' my.json

Solution

  • perl -pe 's("([^"\\]|\\.)*"){$i=1;$&=~s(%s){"%".$i++."\$s"}ger}ge' my.json
    

    How it works

    • option -p : assume loop like -n but print line also, like sed (from perl -h)
    • s/// the substitution operator
    • () and {} as delimiters because when balanced nesting is allowed
    • /e modifier: Evaluate the right side as an expression.
    • /r modifier: Return substitution and leave the original string untouched. (useful because $& readonly and avoids using another variable)