Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
howto:edit-ed [2015/08/08 21:08]
bill_thomson [Editing files with the ed text editor from scripts]
howto:edit-ed [2015/08/08 22:00] (current)
bill_thomson
Line 5: Line 5:
 ===== Why ed? ===== ===== Why ed? =====
  
-Unlike ​''​sed'',​ ''​ed''​ is really ​file editor. ​If you try to change file contents with ''​sed'',​ and the file is open elsewhere and read by some process, you will find out that GNU ''​sed''​ and its ''​-i''​ option ​of course does not edit in-file. There are circumstances where you may need that, either ​editing active and open files or not having ​GNU ''​sed'' ​or some other ''​sed''​ with "​in-place"​ option available.+Like ''​sed'',​ ''​ed''​ is a line editor. ​However, if you try to change file contents with ''​sed'',​ and the file is open elsewhere and read by some process, you will find out that GNU ''​sed''​ and its ''​-i''​ option ​will not allow you to edit the file. There are circumstances where you may need that, e.g. editing active and open files, the lack of GNUor other ''​sed''​with "​in-place"​ option available.
  
 Why ''​ed''?​ Why ''​ed''?​
Line 13: Line 13:
   * last but not least: standard ''​ed''​ has very good editing and addressing possibilities,​ compared to standard ''​sed''​   * last but not least: standard ''​ed''​ has very good editing and addressing possibilities,​ compared to standard ''​sed''​
  
-Don't get me wrong, this is **not** meant as anti-''​sed''​ article! It's just meant to show you another way that may do the job.+Don't get me wrong, this is **not** meant as anti-''​sed''​ article! It's just meant to show you another way to do the job.
  
  
Line 20: Line 20:
 ===== Commanding ed ===== ===== Commanding ed =====
  
-Since ''​ed''​ is an interactive text editor, it reads and executes commands that come from ''​stdin''​. ​Regarding this, we have several ways to feed our commands to it:+Since ''​ed''​ is an interactive text editor, it reads and executes commands that come from ''​stdin''​. ​There are several ways to feed our commands to ed:
  
 **__Pipelines__** **__Pipelines__**
Line 27: Line 27:
 </​code>​ </​code>​
  
-To inject the needed newlines etc. it can be easier to use the ''​printf'' ​builtin ​("help printf"​)here as an example ​for a complete ​Bash function to precede ​text to a filecontent:+To inject the needed newlinesetc. it may be easier to use the builtin command, ​''​printf''​ ("help printf"​). Shown here as an example Bash function to prefix ​text to file content:
 <​code>​ <​code>​
  
Line 49: Line 49:
 </​code>​ </​code>​
  
-Which one you prefer is your own problem ;-) I will use the here-strings,​ since it looks best here IMHO.+Which one you prefer is your choice. ​I will use the here-strings,​ since it looks best here IMHO.
  
-Of course there are some other ways to provide ​the standard ​input to ''​ed''​, for example ​using process substitution. But these should be enough for daily needs.+There are other ways to provide input to ''​ed''​. For exampleprocess substitution. But these should be enough for daily needs.
  
-Since ''​ed''​ wants commands separated by newlines, I'll use a special Bash quoting method, the C-like strings ''<​nowiki>​$'​TEXT'</​nowiki>'',​ as it can interpret a various ​set of escape sequences and special characters. I'​ll ​also usually ​use the ''​-s''​ option ​to ''​ed'' ​to make it less babbling.+Since ''​ed''​ wants commands separated by newlines, I'll use a special Bash quoting method, the C-like strings ''<​nowiki>​$'​TEXT'</​nowiki>'',​ as it can interpret a set of various ​escape sequences and special characters. I'll use the ''​-s''​ option to make it less verbose.
  
  
Line 59: Line 59:
 ===== The basic interface ===== ===== The basic interface =====
  
-Of course, check the ''​ed''​ manpage for a detailed reference!+Check the ''​ed''​ manpage for details
  
-''​ed''​ makes (similar ​to ''​vi''​ or ''​vim''​) a difference between ​a "​command mode" and an "​interactive mode". For non-interactive use, the command mode will be the most used one.+Similar ​to ''​vi''​ or ''​vim''​, ''​ed''​ has a "​command mode" and an "​interactive mode". For non-interactive use, the command mode is the usual choice.
  
-Commands to ''​ed''​ have a simple and regular structure: zero, one, or two addresses followed by a single-character command, possibly followed by parameters to that command. These addresses specify one or more lines in the text buffer. Every command that requires addresses has default addresses, so that the addresses ​very often can be omitted.+Commands to ''​ed''​ have a simple and regular structure: zero, one, or two addresses followed by a single-character command, possibly followed by parameters to that command. These addresses specify one or more lines in the text buffer. Every command that requires addresses has default addresses, so the addresses can often be omitted.
  
-The line addressing is relative to the so-called ​//current line//. If the edit buffer is not empty, the initial value for the //current line// shall be the last line in the edit buffer, otherwise zero. Generally, the //current line// is the last line affected by a command. All addresses can only address single lines, not blocks of lines!+The line addressing is relative to the //current line//. If the edit buffer is not empty, the initial value for the //current line// shall be the last line in the edit buffer, otherwise zero. Generally, the //current line// is the last line affected by a command. All addresses can only address single lines, not blocks of lines!
  
-Line addresses or commands using //regular expressions//​ interpret ​the POSIX Basic Regular Expressions (BRE). A null BRE is used to reference the most recent ​used BRE. Since ''​ed''​ addressing is only for single lines, no RE can ever match a newline.+Line addresses or commands using //regular expressions//​ interpret POSIX Basic Regular Expressions (BRE). A null BRE is used to reference the most recently ​used BRE. Since ''​ed''​ addressing is only for single lines, no RE can ever match a newline.
  
  
Line 73: Line 73:
 ===== Debugging your ed scripts ===== ===== Debugging your ed scripts =====
  
-By default ''​ed''​ is not very talkative and will simply print a "?"​ when an error occurs. Interactively you can use the ''​h''​ command to get a short message explaining the last error. You can also turn on a mode that makes ''​ed'' ​prints ​automatically this message with the ''​H''​ command. It is a good idea to always add this command ​in front of all your ed scripts:+By default''​ed''​ is not very talkative and will simply print a "?"​ when an error occurs. Interactively you can use the ''​h''​ command to get a short message explaining the last error. You can also turn on a mode that makes ''​ed''​ automatically ​print this message with the ''​H''​ command. It is a good idea to always add this command ​at the beginning ​of your ed scripts:
  
 <​code>​ <​code>​
Line 81: Line 81:
 </​code>​ </​code>​
  
-While working on your script, you might make errors and destroy your file, you might be tempted to first try your script doing something like:+While working on your script, you might make errors and destroy your file, you might be tempted to try your script doing something like:
 <​code>​ <​code>​
 # Works, but there is better # Works, but there is better
Line 99: Line 99:
 ed -s file <<<​ $'​H\n<​ed commands>​\n,​p'​ ed -s file <<<​ $'​H\n<​ed commands>​\n,​p'​
 </​code>​ </​code>​
-the '',''​ (comma) in front of the ''​p''​ command is a shortcut for ''​1,​$''​ which defines an address range for the first to the last line, '',​p''​ thus means print the whole file, after it has been modified. When your script ​works you only have to replace the '',​p''​ by a ''​w''​.+the '',''​ (comma) in front of the ''​p''​ command is a shortcut for ''​1,​$''​ which defines an address range for the first to the last line, '',​p''​ thus means print the whole file, after it has been modified. When your script ​runs sucessfully, ​you only have to replace the '',​p''​ by a ''​w''​.
  
-Of course, even if the file is not modified by the ''​p''​ command, **it is always a good idea to keep backups around.**+Of course, even if the file is not modified by the ''​p''​ command, **it'​s ​always a good idea to have a backup copy!**
    
  
 ===== Editing your files ===== ===== Editing your files =====
  
-Most of these things can be done with ''​sed''​, yes. But there are also things that can't be done in ''​sed''​ or can only be done with very complex code.+Most of these things can be done with ''​sed''​. But there are also things that can't be done in ''​sed''​ or can only be done with very complex code.
  
  
Line 115: Line 115:
 ==== Simple word substitutions ==== ==== Simple word substitutions ====
  
-Like ''​sed'',​ ''​ed''​ also knows the common ''​s/​FROM/​TO/''​ command and it also can take line-addresses. **If no substitution is made on the addressed lines, it's considered ​as an error.**+Like ''​sed'',​ ''​ed''​ also knows the common ''​s/​FROM/​TO/''​ commandand it can also take line-addresses. **If no substitution is made on the addressed lines, it's considered an error.**
  
 === Substitutions through the whole file === === Substitutions through the whole file ===
Line 132: Line 132:
 </​code>​ </​code>​
  
-On the 5th line after line containing ''​fruits'',​ do the substitution:​+On the 5th line after the line containing ''​fruits'',​ do the substitution:​
 <​code>​ <​code>​
 ed -s test.txt <<<​ $'/​fruits/​+5s/​apple/​banana/​g\nw'​ ed -s test.txt <<<​ $'/​fruits/​+5s/​apple/​banana/​g\nw'​
Line 158: Line 158:
 ...using the ''​m''​ command: ''<​ADDRESS>​ m <​TARGET-ADDRESS>''​ ...using the ''​m''​ command: ''<​ADDRESS>​ m <​TARGET-ADDRESS>''​
  
-This is definitely ​a thing that can't be done in sed that easy.+This is definitely ​something ​that can't be done easily with sed.
  
 <​code>​ <​code>​
Line 174: Line 174:
  
 <​code>​ <​code>​
-# make a copy of lines 5-9 and place it to the end of the file+# make a copy of lines 5-9 and place it at the end of the file
 ed -s test.txt <<<​ $'​5,​9t$\nw'​ ed -s test.txt <<<​ $'​5,​9t$\nw'​
  
-# make a copy of lines 5-9 and place it to line 3+# make a copy of lines 5-9 and place it at line 3
 ed -s test.txt <<<​ $'​5,​9t3\nw'​ ed -s test.txt <<<​ $'​5,​9t3\nw'​
 </​code>​ </​code>​
Line 195: Line 195:
 === Insert another file === === Insert another file ===
  
-How to insert another file? Just as in ''​sed'', ​it's done by the ''​r'' ​command ​(read). ​This one inserts another file at the line before the last line (and printd ​the result to stdout - '',​p''​):​+How do you insert another file? As with ''​sed'', ​you use the ''​r''​ (read) ​commandThat inserts another file at the line before the last line (and prints ​the result to stdout - '',​p''​):​
 <​code>​ <​code>​
 ed -s FILE1 <<<​ $'$-1 r FILE2\n,​p'​ ed -s FILE1 <<<​ $'$-1 r FILE2\n,​p'​
 </​code>​ </​code>​
  
-To compare, here's a possible ''​sed''​ solution which must use Bash arithmetics ​and the external program ''​wc'':​+To compare, here's a possible ''​sed''​ solution which must use Bash arithmetic ​and the external program ''​wc'':​
 <​code>​ <​code>​
 sed "​$(($(wc -l < FILE1)-1))r FILE2" FILE1 sed "​$(($(wc -l < FILE1)-1))r FILE2" FILE1
Line 229: Line 229:
 on each line so this command will search the next line matching foo and delete it. on each line so this command will search the next line matching foo and delete it.
 If you want to delete all lines matching foo, or do a subsitution on all lines matching foo If you want to delete all lines matching foo, or do a subsitution on all lines matching foo
-you have to tell ed about it with the g command:+you have to tell ed about it with the g (global) ​command:
  
 <​code>​ <​code>​
Line 244: Line 244:
 **__ an error stops the script __** **__ an error stops the script __**
  
-You might think that it's not a problem and that the same thing happens with sed and you're right, with the exception that with ed +You might think that it's not a problem and that the same thing happens with sed and you're right, with the exception that if ed 
-not finding ​a pattern ​is an error while sed just continue ​with the next line. +does not find a pattern ​it'​s ​an errorwhile sed just continues ​with the next line. 
-For instance, let's say that you want to change foo by bar on the first line of the file and add something after the next line,+For instance, let's say that you want to change foo to bar on the first line of the file and add something after the next line,
 ed will stop if it cannot find foo on the first line, sed will continue. ed will stop if it cannot find foo on the first line, sed will continue.
  
Line 258: Line 258:
  
 If you want the same behaviour you can use g/foo/ to trick ed. g/foo/ will apply the command on all lines matching foo, If you want the same behaviour you can use g/foo/ to trick ed. g/foo/ will apply the command on all lines matching foo,
-thus the substitution will succeed and ed will not goe into error if foo is not found:+thus the substitution will succeed and ed will not produce an error when foo is not found:
  
 <​code>​ <​code>​
Line 265: Line 265:
 </​code>​ </​code>​
  
-In fact even a substitution that fails after a g/ / commands ​does not seem to cause an error ie you can also+In facteven a substitution that fails after a g/ / command ​does not seem to cause an error, i.e. you can 
 use a trick like g/​./​s/​foo/​bar/​ to attempt the substitution on all non blank lines  ​ use a trick like g/​./​s/​foo/​bar/​ to attempt the substitution on all non blank lines  ​
  
Line 272: Line 272:
 **__ shell parameters are expanded __** **__ shell parameters are expanded __**
    
-If you don't quote the delimiter, $ has a special meaning. This sounds obvious but is +If you don't quote the delimiter, $ has a special meaning. This sounds obvious but it's 
-easy to forget this fact when you use address ​like $-1 or command ​like $a. Either quote the $ or the delimiter:+easy to forget this fact when you use addresses ​like $-1 or commands ​like $a. Either quote the $ or the delimiter:
 <​code>​ <​code>​
 #fails #fails
Line 303: Line 303:
  
 The . used to terminate the command "​a"​ must be the only thing on the line. The . used to terminate the command "​a"​ must be the only thing on the line.
-take care of it if you indent the commands:+take care if you indent the commands:
  
 <​code>​ <​code>​
-#ed don't care for the spaces before the commands, but . must be the only thing on the line:+#ed doesn't care about the spaces before the commands, but the . must be the only thing on the line:
 ed -s file << EOF ed -s file << EOF
     a     a
Line 317: Line 317:
 ===== Simulate other commands ===== ===== Simulate other commands =====
  
-Keep in mind that in all the examples below, the whole file will be read into the memory.+Keep in mind that in all the examples below, the entire ​file will be read into memory.
  
 ==== A simple grep ==== ==== A simple grep ====
Line 328: Line 328:
 </​code>​ </​code>​
  
-**__Note:​__** Rumors tell that the name of the command ​''​grep'' ​might be related to the notaion ''​g/​RE/​p''​ (global => regular expression => print).+The name ''​grep'' ​is derived from the notaion ''​g/​RE/​p''​ (global => regular expression => print). 
 +ref http://​www.catb.org/​~esr/​jargon/​html/​G/​grep.html
  
  
Line 334: Line 335:
 ==== wc -l ==== ==== wc -l ====
  
-Since the default ​line for the ''​ed'' ​command to print the line number is the last line, a simple ''​=''​ (equal sign) will print this line number and thus the number of lines of the file:+Since the default for the ''​ed'' ​"print line number" command ​is the last line, a simple ''​=''​ (equal sign) will print this line number and thus the number of lines of the file:
  
 <​code>​ <​code>​
Line 348: Line 349:
 </​code>​ </​code>​
  
-...but a similar thing to ''​cat''​ showing line-endings and escapes can be done with the ''​list''​ command (l):+...but a similar thing to ''​cat''​ showing line-endings and escapes can be done with the ''​list''​ command (l):
  
 <​code>​ <​code>​