0

Say I have the following file:

public class Foo {
   // Some code
   // There will be functions here, so there are other {}

   // I WANT TO INSERT HERE
}

I want to insert a function inside the Foo class. This would be right before the last occurrence of }.

How can I do this in sed?

Edit

How about a script that works on both Mac and Linux?

Kousha
  • 32,871
  • 51
  • 172
  • 296
  • Is there more than one } ? If not do a replace } with $Yourstuff } like this sed "s/}/$yourstuff }/" – Mike Wodarczyk Feb 22 '17 at 03:08
  • @MikeWodarczyk, yes there will be more `}` – Kousha Feb 22 '17 at 03:11
  • 1
    Is there more than one `}` with no preceding whitespace? – choroba Feb 22 '17 at 03:11
  • Can you put the string "// I want to insert here " into the file? Then you can replace this string with what you want to go there. – Mike Wodarczyk Feb 22 '17 at 03:13
  • 1
    It's not clear how you distinguish the `}` that closes the class from any other `}` that might be in the file. You really need something that can parse whatever language is in the file, not a regular expression. – chepner Feb 22 '17 at 04:41
  • Please let us know [what you have tried](http://whathaveyoutried.com/). Most of us here are happy to help you improve your craft, but are less happy acting as short order unpaid programming staff. Show us your work so far in an [MCVE](http://stackoverflow.com/help/mcve), the result you were expecting and the results you got, and we'll help you figure it out. – ghoti Feb 22 '17 at 20:49

4 Answers4

3
sed '$s/\(}\)/Put thing here\n\1/' 

$ in front matches last line straight away, so it won't work if the } is not on the last line of the file.

Munir
  • 3,442
  • 3
  • 19
  • 29
  • Feel free to downvote if you must. I have specified exactly when my sed will work. I don't see enough info in the question whether the } is on last line or not, so just putting in a simple answer for a simple situation. – Munir Feb 22 '17 at 04:43
  • Nah I can't do that, and I wasn't criticizing your efforts, just the behavior on OS X places the string in the {} before the last }. – l'L'l Feb 22 '17 at 04:47
  • Sorry...i did not know that. I tested this on linux with GNU sed. – Munir Feb 22 '17 at 04:49
  • @l'L'l - no, OS X uses a sed that came from FreeBSD, not GNU sed at all. Perhaps you're thinking of `grep`. – ghoti Feb 22 '17 at 20:54
  • @ghoti: Maybe that was it; my point being the same tool can differ across platforms ( in operation and result ). The OP didn't specify which they were using, but something to possibly be aware of anyway. – l'L'l Feb 23 '17 at 00:33
1

try this:

sed -i '/^\(}\)/ i new_function' file

Worked on me on Debian.

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Luke
  • 11
  • 1
0

Assuming more than a single class and possibly other data in the file:

sed '/Foo/,/^}/s%^}%\t//New insert\n}%' file

At the end of the day you can always find something that won't quite work with your solution, so you may need to know your data :)

Below will also cope with class definition all on one line:

sed -e '/Foo/,/^}/s%^}%\t//New insert\n}%' -e '/Foo.*}$/s%}$%\t //New insert\n}%' file
grail
  • 914
  • 6
  • 14
  • If the class is all one line (eg. `class { ... {} }`) this doesn't work... also on some versions of `sed` the `\t` or `\n` will end up printing just `t` or `n` instead of a tab/new line. – l'L'l Feb 22 '17 at 04:18
0

This does the job with GNU Sed 4.2.2 at RedHat (you can test it here if you like)

$ sed -n '/class Foo2 {/,/^}$/{s/^}$/Insert here\n\0/};p' file

I assumed that the file could contain more classes , and i try to insert my text (insert here) before the end of class Foo2 in the middle of file.

Testing:

$ cat file2
public class Foo {
   // Some code
   // There will be functions here, so there are other {}
}
public class Foo2 {
   // Some code
   // There will be functions here, so there are other {}
}
public class Foo3 {
   // Some code
   // There will be functions here, so there are other {}
}


$ sed -n '/class Foo2 {/,/^}$/{s/^}$/Insert here\n\0/};p' file2
public class Foo {
   // Some code
   // There will be functions here, so there are other {}
}
public class Foo2 {
   // Some code
   // There will be functions here, so there are other {}
Insert here
}
public class Foo3 {
   // Some code
   // There will be functions here, so there are other {}
}

Explanation:
/class Foo2 {/ , /^}$/ - The range - from class name Foo2 { up to first ^}$
{s/^}$/Insert here\n\0/} - The replacement part . Replace ^}$ with your text plus new line plus replaced part \0
;p : Print

Update for BSD
With the fantastic help of @ghoti and after setting up a FreeBSD machine for testing, this seems to work on FreeBSD (bash only):

sed -n "/class Foo2 {/,/^}\$/{s/^}\$/Insert here \\"$'\n'" &/;};p" file

Mind that if shell is not bash, this will not work. You can give a try anyway.

George Vasiliou
  • 6,130
  • 2
  • 20
  • 27
  • @Kousha Hm... not good. I also tried with sed --posix and worked fine. What sed version do you use? – George Vasiliou Feb 22 '17 at 21:25
  • @Kousha By the way , you know that you can install gsed = gnu sed on your mac, right? http://stackoverflow.com/questions/30003570/how-to-use-gnu-sed-on-mac-os-x – George Vasiliou Feb 22 '17 at 21:54
  • The script will work in non-GNU sed just fine with simple adjustments that will also work in GNU sed. Portability is about making your code run in multiple implementations of a language, not about making a particular implementation ubiquitous across multiple systems. – ghoti Feb 23 '17 at 01:08
  • @ghoti You are right, a good code must be portable. I'm an amateur and i'm not able to test my script to a non-GNU sed... If you have any idea how to test this, i'm willing to fix it. PS: I did not find any online terminals equipped with non-GNU sed to make the necessary adjustments (i.e something similar to tutorialspoint bash online terminal that i used ) – George Vasiliou Feb 23 '17 at 01:13
  • @ghoti by the way, seems strange to me that this script run succesfully with --posix switch which theoritically disables gnu extensions. Obviously gnu sed --posix vs non-gnu sed have more differences. – George Vasiliou Feb 23 '17 at 01:16
  • The basic differences here are that `\n` and `\0` are GNU-isms, and the closing curly brace of a function should have a semicolon before it. I can't speak to GNU sed's `--posix` option, because I don't use GNU sed. You'd be closer to a portable solution with `sed -n '/class Foo2 {/,/^}$/{s/^}$/Insert here&/;};p' file`, though that doesn't insert a line, it just inserts data before the closing curly brace (which is likely syntactically valid, but isn't so pretty). You could also use: `sed -n "/class Foo2 {/,/^}\$/{s/^}\$/Insert here\\"$'\n'"&/;};p" file` if you like. – ghoti Feb 23 '17 at 22:03
  • @ghoti thanks for all the info. I am aware for the usage of & instead of \0, but i didn't know that & is portable while \0 is gnu only. I will replace \0 with &. About new line is the hex `\x0a` accepted as new line instead of \n? GNU sed accepts \x0a raw,as it is seen. – George Vasiliou Feb 23 '17 at 22:26
  • FreeBSD and OSX's sed does not accept hex codes like that. You can check [the man page](https://www.freebsd.org/cgi/man.cgi?query=sed) if you like. Another option might be to use shell format expansion, if your shell supports it: `sed -n $'/class Foo2 {/,/^}$/{s/^}$/\tInsert here\\\n&/;};p' file`. (Bash does, as do newer versions of FreeBSD's `/bin/sh`.) – ghoti Feb 24 '17 at 06:01
  • @Kousha Answer updated with a tested FreeBSD Version under bash. Let me know if it works for you. – George Vasiliou Feb 24 '17 at 10:53
  • @ghoti thank your for your help. I updated my answer. I also made some tests under FreeBSD (with a VM) and your proposals works fine under bash (not under default csh) – George Vasiliou Feb 24 '17 at 10:54
  • No problem. Yes, FreeBSD's `/bin/sh` is based on the Almquist shell, which is neither csh nor bash. It does support format expansion, but `csh` is a different beast entirely. In OS X, `/bin/sh` is in fact a version of `bash` that has been compiled differently. (Have a look at the comments on [this answer](http://stackoverflow.com/a/9712555/1072112) for some background.) – ghoti Feb 24 '17 at 12:30