2

I have a file that has several lines like:

"key1":"val1","key2":"val2","key3":"val3","key4":"val4"

In the vi editor or using sed I want to replace all the text between ":" and "," with ",", i.e. I want to keep all keys and remove all the values.

The line will become like:

"key1","key2","key3","key4"

In vi editor I tried to use :%s/":".*","/","/g, and using sed I used sed 's/":"*","/","/' but instead of replacing the in-between text, it is removing all the text from the first occurrence of ":" and last occurrence ",",i.e. the line is becoming "key1","key4":"val4".

How do I replace the text in-between subsequent occurrences of ":" and following "," ?

Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
aiman
  • 1,049
  • 19
  • 57
  • 2
    `.*` is a monster because `.` matches anything and `*` is greedy. This should help: https://stackoverflow.com/questions/1305853/how-can-i-make-my-match-non-greedy-in-vim – Ruud Helderman Dec 11 '19 at 16:22
  • 2
    Are you trying to manipulate JSON? Like [this](https://jqplay.org/s/WzL18JUPiy)? – Benjamin W. Dec 11 '19 at 16:40
  • 1
    Assuming keys cannot contain `:` and values cannot contain `"`: `:%s/:"[^"]*"//g` or `:%s/":"[^"]*//g` – jhnc Dec 11 '19 at 17:34

1 Answers1

1

Assuming that neither the key nor value can contain ", this sed solution will work:

   sed 's/\("[^"]*"\):"[^"]*"/\1/g'

Explanation:

  • s/ substitute
  • /\("[^"]*"\):"[^"]*"/ search for "stuff":"more stuff", where it is assumed there are no other double-quotes " in stuff, etc., and then capture the first part (with \( and \))
  • /\1/ keep only the first part
  • /g and continue
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
  • **Edit:** If the key or value _can_ contain a double-quote `"`, this solution may be easily modified, once you tell us how the `"` is escaped. (And how the escape is escaped!) – Joseph Quinsey Dec 11 '19 at 21:25