======================================= ed ======================================= ed is the ascii text line editor - the basics of ed is to find and address lines and then run editing commands on them - ed is the command portion of vi - stay away from ESC - stay away from multibyte characters - the command prompt is blank and is always ready - all commands are just a single character - the current line is the default address - print is usually the default command - the most recent line affected or printed will always become the current line - searching by regular expression will wrap to the beginning of the file - addressing line(s) may have a default command such as print - some commands may have a default address such as the current line or all lines - if you have an empty edit buffer or unsaved changes then many commands might return ? - many of the examples below may show variations 1: 2: 3: etc of doing the same thing ======================================= pro tips --------------------------------------- - some characters have magic so to remove the magic just precede it with a \ backslash - some characters are given magic by preceding it with a \ backslash - working by line numbers is not very efficient and is what you want to grow out of - work on addressing lines - work on addressing a range of lines - work on addressing a subset of a range of lines - work on addressing lines using regular expressions - work on regular expressions for editing - you can use ed to edit any ascii text file faster than using a mouse in a gui ======================================= run ed --------------------------------------- # ed - will open an empty edit buffer # ed filename - will open an edit buffer for filename - it may tell you the number of characters in the file OR that the file does not exist yet - the last line of the file will be your current line ======================================= print commands (p) (n) (l) --------------------------------------- # p = print (default) # n = show line numbers # l = show hidden characters # nl = show line numbers and hidden characters # print the entire file 1: ,p 2: %n ======================================= browsing --------------------------------------- # set browsing to 20 lines at a time and start browsing from line 1 1: 1z20 2: z // show the next 20 lines 3: 28z // show the next 20 lines from line 28 4: z28 // show the next 28 lines 5: z // show the next 28 lines ======================================= shell out (!) --------------------------------------- # run a quick shell command without quitting ed 1: !date 2: !cat foo 3: !/path/to/some/script.sh ======================================= buffer commands --------------------------------------- # get a hint when the previous command returns a ? 1: h # get the edit buffer filename (always do this for filename confirmation before you save your file!!!) 1: f # set the edit buffer filename (f) 1: f filename 2: f /path/to/filename # (append) read filename to edit buffer after addressed line (r) 1: r filename // read in filename after current line 2: .r filename 3: 0r filename // read in filename before first line 4: $r /path/to/filename // read in filename after last line 5: $r !script.sh // append output of script.sh to after the last line # (overwrite) save the edit buffer to filename (w) 1: w 2: wq 3: 1,$w 4: 1,5w // save only lines 1 to 5 5: .w // save only the current line 6: $w // save only the last line # (overwrite) save the edit buffer to a different filename (w) 1: w filename 2: w /path/to/filename 3: 1,$w filename 4: .w filename 5: $w filename # (append) save the edit buffer to filename (W) 1: W 2: 1,$W 3: 1,5W 4: .W 5: $W # (append) save the edit buffer to a different filename (W) 1: W filename 2: W /path/to/filename 3: 1,$W filename 4: .W filename 5: $W filename # edit a different file 1: e filename 2: e filename (repeat to edit filename without saving current file) 3: E filename (edit filename without saving current file) # quit 1: q 2: q (repeat to quit without saving current file) 3: Q (quit without saving) ======================================= marking lines for addressing --------------------------------------- # mark the current line as "a" (any lowercase letter) for addressing 1: ka // mark current line as "a" 2: .ka 3: 4kb // mark the fourth line as "b" 4: /this/kc // find next line matching this and mark line as "c" ======================================= get line number command (will not affect current line) --------------------------------------- # get the number of lines in the edit buffer 1: = 2: $= # get the line number of the current line 1: .= # get the line number of line 5 1: 5= // yes it will let you do stupid # get the line number of the previous line 1: -= 2: -1= 3: .-1= # get the line number going back three lines from the current line 1: ---= 2: .---= 3: -3= 4: .-3= # get the line number going forward three lines from the current line 1: +++= 2: .+++= 3: +3= 4: .+3= # get the line number of the line marked "a" 1: 'a= # get the line number going forward three lines from the line marked "a" 1: 'a+3= ======================================= addressing single line --------------------------------------- # current line 1: . 2: p 3: .p # first line 1: 1 2: 1p # last line 1: $ 2: $p # line 28 1: 28 2: 28p # next line 1: [hit enter] // just hit enter to go to the next line 2: + 3: +p 4: .+p 5: .+1p # previous line 1: - 2: -p 3: -1p 4: ^p 5: ^1p # go forward 3 lines 1: +++ 2: +++p 3: +3 4: .+3p # go back 3 lines 1: --- 2: ---p 3: -3 4: .-3p 5: ^3p # line marked "a" 1: 'a 2: 'ap ======================================= addressing single line: search for the next line matching /re/ regular expression --------------------------------------- # match any character (.) 1: /./p # match beginning of line (^) 1: /^/p 2: /^Dear/p # match end of line ($) 1: /$/p 2: /Yours$/p # match blank line 1: /^$/p # match any of these characters within [ class ] 1: /[bcfhmp]at/p 2: /[ \t][bcfhmp]at[ \t$]/p 3: /[0-9]/p // matches: numeric 4: /[0-9a-zA-Z]/p // matches: alphanumeric 5: /[[\]\^\$\.-]/p // remove the magic from ]^$. in class []^$.- 6: /[0-9]*[02468]/p // matches: even numbers # not matching characters within [ class ] 1: /[^cfhmp]at/p // matches: bat 2: /[0-9]*[^13579]/p // matches: even numbers # match zero or more of previous character (*) 1: /.*/p 2: /a*/p 3: /a{0,}/p # match one or more of the previous character 1: /aa*/p 2: /a{1,}/p # match at least one up to an amount of previous character 1: /a{1,10}/p # match empty line 1: /^[ \t]*$/p // there is no \t - it is only me trying to tell you i am looking for a tab character # next line matching /re/ 1: /abc 2: /abc/ 3: /abc\*/p // \* turns the magic off 4: /https:\/\/www.domain.com\/index?abc=1/p // \/ turns the magic off # match tagged regular expression \(re\) // \( and \) turns the magic on, \1 turns the magic on 1: /\( 000\).*\1.*\1/p // matches: " 000 whatever 000 foo bar 000" 2: /\([0-9]*\)-\1-\1/p // matches: "11111-432234241-189023443454" 3: /\(abc\)\(def\)-\2\1/p // matches: "abcdef-defabc" # previous line matching ?re? 1: ?abc 2: ?abc? 3: ?abc?p 4: ?https://www.domain.com/index\?abc=1?p // \? turns the magic off # search for the next occurrence of the same regular expression 1: / 2: // 3: //p # search for the previous occurrence of the same regular expression 1: ? 2: ?? 3: ??p ======================================= addressing a range of lines (,) --------------------------------------- # line 1 to last line 1: ,p 2: %p 3: 1,$p # line 1 to current line 1: 1,. 2: 1,.p # current line to last line 1: ;p 2: .,$p # line 4 to line 8 1: 4,8p 2: 1+++,8p 3: 3+,4++++p 4: 8----,4++++p 5: 8-4,4+4p # back 3 lines to forward 3 lines from the current line 1: ---,+++p 2: ---,+3p 3: .-3,.+++p 4: -3,+3p 5: ^3,+3p # line marked "a" to line marked "b" 1: 'a,'bp # line marked "a" to current line 1: 'a,.p # next line matching /re/ to line marked "a" 1: /abc/,'ap # next line matching /re/ to next line matching /re/ 1: /abc/,/xyz/p ======================================= global match /re/ addressing a subset of a range of lines (g) --------------------------------------- # all lines matching /re/ within an address range 1: g/Name/p 2: %g/Name/p 3: 1,$g/Name/p 4: 'a,'bg/Name/p 5: /Dear/,/Yours/g/Name/p ======================================= global non match /re/ addressing a subset of a range of lines (v) --------------------------------------- # all lines not matching /re/ within an address range 1: v/Name/p 2: %v/Name/p 3: 1,$v/Name/p 4: 'a,'bv/Name/p 5: /Dear/,/Yours/v/Name/p ======================================= append (a) / insert (i) / change (c) commands (to stop enter a . on a line by itself) --------------------------------------- # to stop appending/inserting/changing enter a . on a line by itself 1: . # append text after the addressed line (a) 1: a 2: .a 3: 0a 4: $a 5: 'aa 6: /Hello/a # insert text before the addressed line (i) 1: i 2: .i 3: 1i 4: $i 5: 'ai 6: /Hello/i # change (replace) text of the addressed line(s) (c) 1: c 2: .c 3: 1c 4: $c 5: 'ac 6: /Hello/c 7: 5,9c ======================================= delete command (d) --------------------------------------- # delete addressed line(s) and print the new current line 1: dp 2: .dp 3: ,dp 4: 'a,'bdp 5: /Dear/,/Yours/dp ======================================= move to command (m) --------------------------------------- # move addressed line(s) to after line 1: m // move current line to after current line. does nothing 2: .m 3: .m. 4: .m.p 5: $m0p // move last line to before line 1 6: 1,9m19p // move lines from line 1 to line 9 to after line 19 7: 'a,'bm'cp // move lines from mark "a" to mark "b" to after mark "c" 8: /Dear/,/Yours/m/Name/p // move lines from next Dear to next Yours to after next Name ======================================= copy to command (t) --------------------------------------- # copy addressed line(s) to after line 1: t // copy current line to after current line. duplicates current line. 2: .t 3: .t. 4: .t.p 5: $t0p // copy last line to before line 1 6: 1,9t19p // copy lines from line 1 to line 9 to after line 19 7: 'a,'bt'cp // copy lines from mark "a" to mark "b" to after mark "c" 8: /Dear/,/Yours/t/Name/p // copy lines form next Dear to next Yours to after next Name 9: %t$ // copy all lines to after the last line (duplicate entire file) ======================================= join command (j) --------------------------------------- # join addressed line(s) 1: jp 2: .j 3: .jp 4: 1,$jp 5: 'a,'bjp 6: /Dear/,/Yours/jp ======================================= substitution command replace /re/ regular expressions (s) --------------------------------------- # replace the first occurrence of this for that on addressed line(s) 1: s/this/that/p 2: .s/this/that/p 3: $s/this/that/p 4: 8s/this/that/p 5: 'as/this/that/p 6: /Dear/s/this/that/p 7: %s/this/that/p 8: 'a,'bs/this/that/p # replace the first occurrence with nothing 1: s/this//p # replace the third occurrence (number) 1: s/this//3p 2: s/this/that/3p # replace every occurrence of (g) 1: s/this/that/gp # replace last match with nothing 1: s///p # replace last match with nothing for the twentieth occurrence 1: s///20p # repeat last match and substitution (%) 1: s//%/p // % has magic # repeat last match and substitution on fifth occurrence 1: s//%/5p # repeat last match and substitution on every occurrence 1: s//%/gp # reuse the search regular expression /re/ (&) 1: s/foo/&bar/p // foobar & has magic 2: s/foo/& \& bar/p // foo & bar \& removes the magic 3: s/.*\./&0.0 /p // 123.0.0 \. removes the magic # use tagged regular expression \(re\) (\1) 1: s/\(123\)/abc \1/p // abc 123 2: s/\([0-9]{3}-[0-9]{3}-[0-9]{4}\)/Phone: \1/p // Phone: 555-555-5555 3: s/\([0-9]{3}-[0-9]{3}-[0-9]{4}\)/Phone: \\\1/p // Phone: \555-555-5555 4: s/http:\(www.domain.com\)/https:\/\/\1\//p // https://www.domain.com/ ======================================= undo/redo last change --------------------------------------- # there is only one level undo 1: u 2: up # redo the last undo 1: u 2: up ======================================= some handy one liners --------------------------------------- # invert the file 1: g/^/m0p # invert lines from line 1 to the current line 1: 1,.g/^/m0p # invert lines form current line to the last line and move them to after line marked "a" 1: ;g/^/m'a # copy every line that contains this to after the last line 1: g/this/t$ # keep second field in every line from the current line to the last line 1: ;s/^[^ ]* \([^ ]*\).*$/\1/p # delete blank lines 1: g/^$/d # delete empty lines (i am using \t to show you there is a real tab character typed there) 1: g/^[ \t]*$/d # insert a space at the end of every line 1: %s/$/ /p # join every line 1: %jp # join the first 5 lines 1: 1,5jp # join every other line 1: g/^/jp # use any character as regular expression delimiters to sometimes make commands easier to compose 1: s/http:\/\/www\.domain\.com/https:\/\/www.domain.com\/foo\/bar.html/gp 2: s,http://www\.domain\.com,https://www.domain.com/foo/bar.html,gp 3: g|\(domain\.com\)|s|https*://[^\.]*\.*\1/|https://\1/|gp 4: g/