That _is_ an ex(1) script there. Vi and ex are (usually) the same binary. Well, except for ZZ - that probably only works in visual mode (wq in command mode is equivalent). I hope you didn't really mean an ed(1) script, since everything since BSD2 (IIRC) has ex(1). Although, patch(1) accepts ed(1) scripts... that's the original diff format, in fact (no context at all). So there's no obstacle to using patch, you just have to go back in time a little bit. -Adam
Sean Cody sean@tinfoilhat.ca wrote:
I have a file in which I need to replace a chunk of lines in on a bunch of hosts.
My initial reaction was to use patch but that won't suffice because the chunk of lines will be different on each host (possibly) so the source part of the patch may not aline to the diff.
Then I was doing to do sed but I can't get the 'r' command do work as I need it to.
So I wrote down a series of vi commands to do what I need to do now I just need to convert that into a sed/ex script...
sudo vi $someconfigfile 23,56d 23 r ~/replacement.txt ZZ
So what I'm doing here is just dumping lines 23 through 56 in some file and inserting a replacement chunk of text (my not necessarily be 56-23 lines long).
The question here is... is this possible to do with sed and if so how (my brain wont' make the right connections right now, must need a break/food or something).
Even better how would this be done with ex (as I can do a bunch of manual vi commands, how would one automate a repeatable vi session...)?
I could just run a series of search&replace lines corresponding to each section in the replacement text doc but that's violating the spirit of the problem (ie. replace a chunk of text at an arbitrary point in a file with a different chunk of text located in a different file).
Some rules... solution shouldn't be perl/python/whatever because that won't necessarily be found on the UNIX hosts I'm using or may use in the future. Solution shouldn't use GNU extensions of sed/awk due to those being incompatible with non-GNU systems (ie. sysv,bsd,hp etc.).
Any hits, takers?
-- Sean P.S. I'm doing this as a bit of a personal change management to replay some changes in the distant future (I'm typically using diff/patch for this though this case is a bit a-typical).
Roundtable mailing list Roundtable@muug.mb.ca http://www.muug.mb.ca/mailman/listinfo/roundtable
On 2012-07-30, at 7:55 PM, Adam Thompson wrote:
That _is_ an ex(1) script there. Vi and ex are (usually) the same binary. Well, except for ZZ - that probably only works in visual mode (wq in command mode is equivalent). I hope you didn't really mean an ed(1) script, since everything since BSD2 (IIRC) has ex(1). Although, patch(1) accepts ed(1) scripts... that's the original diff format, in fact (no context at all). So there's no obstacle to using patch, you just have to go back in time a little bit. -Adam
The 'ZZ' note and distinction above was the exact kick in the right direction I needed! My original attempt (before I started this thread) with ex barfed out with a suprisingly unhelpful message related to buffer naming without context. Now I get what I was doing wrong... the commands were somewhat right (ZZ is visual mode only).
The solution (at least on OS X and OpenBSD... will try tomorrow on target OS): sudo ex -c '23,56d|23r ~/replacement.txt|wq' $someconfigfile
I didn't know/remember the ed & patch connection... very cool/interesting, thanks!
The elegance of this solution is... 1 process is created, file is modified _in place_ and doesn't involve temporary files.
Err... that does involve the use of temporary files, it's just hidden from you. I'm not aware of any way around that unless the replacement text happen to be exactly the same length (in bytes) as the original text, in which case you need to use dd(1) with skip= and/or seek= to avoid creating a temporary file. Even sed(1) and/or perl(1) with "-i" will create a temporary file behind the scenes, since there's no magic syscall (nor a physical way) to _slide_ the bits forwards or backwards on the disk!
If you're going for ultimate portability, I recommend you fall back to ed(1), since that can be used either as-is with ed(1) or with patch(1). The command-line invocation will be slightly uglier than than with ex(1), however.
-Adam Thompson athompso@athompso.net (204) 291-7950 - direct (204) 489-6515 - fax
-----Original Message----- From: roundtable-bounces@muug.mb.ca [mailto:roundtable- bounces@muug.mb.ca] On Behalf Of Sean Cody Sent: Monday, July 30, 2012 10:38 PM To: Continuation of Round Table discussion Subject: Re: [RndTbl] Little script puzzle help.
The solution (at least on OS X and OpenBSD... will try tomorrow on target OS): sudo ex -c '23,56d|23r ~/replacement.txt|wq' $someconfigfile
I didn't know/remember the ed & patch connection... very cool/interesting, thanks!
The elegance of this solution is... 1 process is created, file is modified _in place_ and doesn't involve temporary files.
-- Sean
On 2012-07-31 10:59, Adam Thompson wrote:
Err... that does involve the use of temporary files, it's just hidden from you. I'm not aware of any way around that unless the replacement text happen to be exactly the same length (in bytes) as the original text, in which case you need to use dd(1) with skip= and/or seek= to avoid creating a temporary file. Even sed(1) and/or perl(1) with "-i" will create a temporary file behind the scenes, since there's no magic syscall (nor a physical way) to _slide_ the bits forwards or backwards on the disk!
A better way to state my case is 'no temporary files _I_ have to explicitly manage.' I think I'll try a trace on ex and see if it uses a temporary file. I don't see why it wouldn't (as reading in the entire file into a buffer and dumping back to the original file seems kind of dangerous). Academically interesting. I definitely trust the implementation of sed/ed/ex/vi over my scripting abilities to properly manage the temp files. :)
If you're going for ultimate portability, I recommend you fall back to ed(1), since that can be used either as-is with ed(1) or with patch(1). The command-line invocation will be slightly uglier than than with ex(1), however.
Agreed. The ex trick worked _very_ well. Deployment went smoothly on all 30 odd hosts.