0

I have files like this:

class SomeClass
    extends anotherClass
    with moreClassA
    with moreClassB {
    //do some crazy stuff
}

I'd like to add one more class to it like this:

class SomeClass
    extends anotherClass
    with moreClassA
    with moreClassB 
    with oneMoreClassIwant {
    //do some crazy stuff
}

I tried to use sed for replacing like this:

sed -E "s/(Class SomeClass[A-Za-z \n]+)\\{/\1with OneMoreClassIWant/" tmp.scala

but it doesn't work for multi-line matching.

I also noticed an example from this post but failed to adapt it to my case.

αғsнιη
  • 41,407
  • The requirement to use sed seems like a complication. This would be somewhat more comfortable in Awk, and pretty straightforward in Perl, where nonstandard sed things like -z are actually reasonably standard if you have Perl in the first place. – tripleee Dec 31 '22 at 08:37
  • If the new line (with oneMoreClassIwant) is allowed to appear after the line "class SomeClass" then sed '/class /a with oneMoreClassIwant' should do it. – dhm Dec 31 '22 at 17:11

2 Answers2

1

Using any awk:

$ cat tst.awk
{ rec = rec $0 RS }
END {
    old = \
        "class SomeClass" RS\
        "    extends anotherClass" RS\
        "    with moreClassA" RS\
        "    with moreClassB {" RS\
        "    //do some crazy stuff" RS\
        "}"
new = \
    "class SomeClass" RS\
    "    extends anotherClass" RS\
    "    with moreClassA" RS\
    "    with moreClassB" RS\
    "    with oneMoreClassIwant {" RS\
    "    //do some crazy stuff" RS\
    "}"

if ( s = index(rec,old) ) {
    rec = substr(rec,1,s-1) new substr(rec,s+length(old))
}

printf "%s", rec

}

$ awk -f tst.awk file
class SomeClass
    extends anotherClass
    with moreClassA
    with moreClassB
    with oneMoreClassIwant {
    //do some crazy stuff
}
Ed Morton
  • 31,617
0

This seems to work:

xargs -0 < data | sed -z 's/\(class.*\){/\1\n    with anotherMoreClass {/'

or

tr '\n' '\0' < data | sed 's/\(class.*\){/\1\n    with anotherMoreClass {/' | tr '\0' '\n'

You can specify the class name (SomeClass in your case) in this section: \(class.*\) like this:

xargs -0 < data |\
sed -z  's/\(class[[:blank:]]\{1,\}SomeClass.*\){/\1\n    with anotherMoreClass {/'

or

tr '\n' '\0' < data |\
sed 's/\(class[[:blank:]]\{1,\}SomeClass.*\){/\1\n    with anotherMoreClass {/' |\
tr '\0' '\n'
  • 1
    sed -z is not portable; it is supported on most Linuxes, but not on many other platforms. – tripleee Dec 31 '22 at 08:38
  • @tripleee thanks! I was not really sure about the portability of -z. So I think the better option here is about using tr – Edgar Magallon Dec 31 '22 at 08:47
  • 1
    tr '\n' '\0' turns the input into something that is no longer a valid text file and so YMMV with what any subsequent text processing tool (such as sed) might do with it. – Ed Morton Jan 03 '23 at 00:21
  • @EdMorton with sed seems to work correctly, unless in Linux (gnu sed). In this case I had to use SomeClass.* since sed is interpreting \0 as a character (not sure how this works and also I've never tried to search null characters in commands such as sed,awk, grep.. ) – Edgar Magallon Jan 03 '23 at 05:24
  • 1
    The issue with \0 is that many tools are written in C and in C a \0 is the "end of string" character and so a variable thats a string can't contain a \0. So, what any given sed, grep, awk, etc. can do with input that contains \0 just depends on whatever whoever implemented that tool decided to do with it. If they can accept it then its just a character, no different than any other (unless they additionally provide an option to use that character as the record terminator instead of \n). Even a command that accepts NULs today could decide not to in their next release though so YMMV – Ed Morton Jan 03 '23 at 12:08
  • 1
    @EdMorton Interesting,I had forgotten how C works (about the "end of string"). I tested the same command tr '\0' '\n' | sed ... on busybox and it did not work. So as you said this depends on whatever whoever implemented that tool decided to do with it – Edgar Magallon Jan 03 '23 at 22:20
  • 1
    The thing is, you cant really tell if "it works" in any given tool since there might be some cases where it doesn't behave as you expect and even if it did work today, it might quietly stop working in the next release (unless it's specifically stated in the documentation for that tool that it will work) since the implementers aren't required to keep doing the same thing consistently across releases for anything that's undefined behavior. – Ed Morton Jan 04 '23 at 15:45
  • @EdMorton hopefully this keeps working, and maybe in the case of GNU sed both solutions I provided will still work in next releases or unless the solution about using sed -z is the best in the case of GNU sed but not for portability. Or another posible solution about tr '\0' '\n' is to change \0 with another posible character that doesn't appear in the text file. But I don't really like this solution – Edgar Magallon Jan 04 '23 at 21:58