简体   繁体   中英

How do I replace strings on optional multiple-lines in sed?

I have the following string:

Title 1:::::some message

Title 2:::::another message

Title 3:::::this time

- a longer
- message
- here

Title 4:::::another short one

Title 5:::::and another

- longish
- one here

I am trying to replace the above with sed to have the following format:

{ "values" : [{"title":"Title 1","message":"some message"}]},

{ "values" : [{"title":"Title 2","message":"another message"}]},

{ "values" : [{"title":"Title 3","message":"this time

- a longer
- message
- here"}]},

{ "values" : [{"title":"Title 4","message":"another short one"}]},

{ "values" : [{"title":"Title 5","message":"and another

- longish
- one here"}]},

I know this may be easier with Perl but I'd specifically like to know how to do it with sed . As you can see, it may or may not be a multi-line match.

So far I have:

sed 'N; s/\(.*\):::::\(.*\)/{ "values" : [{"title":"\1","message":"\2"}]},/'

Which results in the following:

{ "values" : [{"title":"Title 1","message":"some message
"}]},
{ "values" : [{"title":"Title 2","message":"another message
"}]},
{ "values" : [{"title":"Title 3","message":"this time
"}]},
- a longer
- message
- here

{ "values" : [{"title":"Title 4","message":"another short one
"}]},
{ "values" : [{"title":"Title 5","message":"and another
"}]},
- longish
- one here

What's the best way to accomplish this properly with sed ?

You can use awk:

awk -F ':{5}' 'function write(t, m) {
   printf "{ \"values\" : [{\"title\":\"%s\",\"message\":\"%s\"}]},\n\n", t, m 
}
NF==2 {
   if (m != "")
      write(t, m)
   t=$1
   m=$2
   next
}
NF {
   m = m ORS $0
}
END {
   write(t, m)
}' file

Output:

{ "values" : [{"title":"Title 1","message":"some message"}]},

{ "values" : [{"title":"Title 2","message":"another message"}]},

{ "values" : [{"title":"Title 3","message":"this time
- a longer
- message
- here"}]},

{ "values" : [{"title":"Title 4","message":"another short one"}]},

{ "values" : [{"title":"Title 5","message":"and another
- longish
- one here"}]},

You can use this mess if you want to use sed

:1
/\n[^\n]*:::::/!{
   $!{
   N
   b1
   }
}
h
s/\n[^\n]*:::::[^\n]*$//
s/\(.*\):::::\(.*[^\n]\)\n\?/{ "values" : [{"title":"\1","message":"\2"}]},/
p
$!{
   x
   s/.*\n//
   b1
}
d

It gets very cryptic using sed only but this is the simplest 1-liner I could form:

$ cat file
Title 1:::::some message

Title 2:::::another message

Title 3:::::this time

- a longer
- message
- here

Title 4:::::another short one

Title 5:::::and another

- longish
- one here
$ sed -r '/^Title\s*[0-9]+/ {s/^(Title\s*[0-9]+):::::(.*)$/"}]}\n{ "values" : [{"title":"\1","message":"\2/}; $a"}]}' file | sed -n -r '1!{/^$/!p}'
{ "values" : [{"title":"Title 1","message":"some message
"}]}
{ "values" : [{"title":"Title 2","message":"another message
"}]}
{ "values" : [{"title":"Title 3","message":"this time
- a longer
- message
- here
"}]}
{ "values" : [{"title":"Title 4","message":"another short one
"}]}
{ "values" : [{"title":"Title 5","message":"and another
- longish
- one here
"}]}
$

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