简体   繁体   中英

sed - trying to replace first occurrence after a match

I am facing a situation that drives me nuts. I am setting up an update server which uses a json file. Don't ask why or how, it sucks and is my only possibility to achieve it.

I have been trying and researching for HOURS (many) because I went ballistic and wanted to crack this on my own. But I have to realize I got stuck and need help.

So sorry for this chunk but I think it is somewhat important to see...

The file is a one liner and repeating the following sequence with changing values (of course).

"plugin_name_foo_bar": {"buildDate": "bla", "dependencies": [{"name": "bla", "optional": true, "version": "1.00"}], "developers": [{"developerId": "bla", "email": "bla@gmail.com", "name": "Bla bla2nd"}], "excerpt": "some text {excerpt} !bla.png|thumbnail,border=1! ", "gav": "bla", "labels": ["report", "scm-related"], "name": "plugin_name_foo_bar", "previousTimestamp": "bla", "previousVersion": "1.0", "releaseTimestamp": "bla", "requiredCore": "1", "scm": "github.com", "sha1": "ynnBM2jWo25ZLDdP3ybBOnV/Pio=", "title": "bla", "url": "http://bla.org", "version": "1.0", "wiki": "https://bla.org"}, "Exclusion": {"buildDate": "bla", "dependencies": [],

and the next plugin block is glued straight afterwards. What I now want to do is to search for "plugin_foo_bar": {" as this is the unique identifier for a new plugin description block. I want to replace the first sha1 value occuring afterwards. That's where I keep failing. I always grab the first,last or any occurrence in the entire file and not the block :( "title" is the unique identifier after the sha1 value.

So I tried to make the .* less greedy but it ain't working out.

last attempt was heading towards: sed -i 's/("name": "plugin_name_foo_bar.*sha1": ")([a-zA-Z0-9!@#\\$%^&*()\\[\\]]*)(", "title"\\)/\\1blablabla\\2/1' default.json

to find the sha1 value of that plugin but still no joy. I hope someone knows - preferably a simpler approach - before I now continue with trial and error until I have to puke and freakout.

I am working with SED on Windows, so Unix approach might help me to figure out how to achieve this in batch but please make it as one-liner if possible. Scripts are a real pain to convert.

And I just need SED and no other solution with other tools like AWK. That is absolutely out of discussion.

Any help is appreciated :)

Cheers Jan

Don't use regex (sed) to parse JSON, instead use a proper JSON parser, or javascript directly like I do :

Using and in a script :

File /tmp/file.json is :

{
   "plugin_name_foo_bar" : {
      "excerpt" : "some text {excerpt} !bla.png|thumbnail,border=1! ",
      "dependencies" : [
         {
            "name" : "bla",
            "version" : "1.00",
            "optional" : true
         }
      ],
      "title" : "bla",
      "previousTimestamp" : "bla",
      "releaseTimestamp" : "bla",
      "sha1" : "ynnBM2jWo25ZLDdP3ybBOnV/Pio=",
      "labels" : [
         "report",
         "scm-related"
      ],
      "buildDate" : "bla",
      "version" : "1.0",
      "previousVersion" : "1.0",
      "name" : "plugin_name_foo_bar",
      "scm" : "github.com",
      "url" : "http://bla.org",
      "gav" : "bla",
      "developers" : [
         {
            "email" : "bla@gmail.com",
            "developerId" : "bla",
            "name" : "Bla bla2nd"
         }
      ],
      "wiki" : "https://bla.org",
      "requiredCore" : "1"
   },
   "Exclusion" : {
      "dependencies" : [],
      "buildDate" : "bla"
   }
}

The script script.js :

var js = require('/tmp/file.json')

js.plugin_name_foo_bar.sha1 = "xxx"
console.log(js)

Usage :

nodejs script.js

As sputnick points out parsing is a little beyond what sed's meant for. Still, sed's Turing-complete and bludgeoning it into doing what you want can satisfy that {sad,masoch}istic urge so many of us feel from time to time.

This one's even easy.

sed '
   s/"sha1": /\n/g
   s/\("name": "plugin_name_foo_bar"[^\n]*\n"\)[^"]*/\1thenewsha/
   s/\n/"sha1": /g
'

对于Windows命令行,使用转义引号,替换内联并使用正则表达式

sed -i -r "s/(plugin_name_foo_bar.+?sha1\": \")[^\"]+\"/\1abcdefghijkl\"/" default.json
sed -r "s/(plugin_name_foo_bar[^!]+sha1.: .)[^\"]+/\1abcdefghijkl/" file

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM