yelt: a stream text editor similar to sed but with more internal variables, user definable functions, escape sequence handling, cut program and tr program features, and simplified parsing support. For more information, see http://www.bordoon.com/yelt Invocation: yelt [options] [files] options: -f file use script specified in file -S string use script specified in string -e cmd add 1 extension command to the default script -l turn on diagnostic logging -M file define string mapping file -D char set the map file delimiter for key/value pairs Yelt's Default script: w { n; [ -e extensions ] ; p; } Where this script means: Repeatedly read the next line, execute any user supplied commands (ie -e options) and print each line. Writing scripts: Don't forget to put your own 'w { n; ... p; }' wrapper in your script file or your -S option string! Comments may be added to script files by adding lines that begin with the # character. These are the only comments supported. The map file is optional and defines the mapping for the 'M' command. The -M option may be used multiple times and the delimiter option. -D can also be used multiple times: use -D before -M. If the option, '-f -' is specified, then the script is read from stdin. Script language overview Yelt's command language is very similar in look and feel to that of SED. Yelt has more variables and different commands, but it is very SED-like. The commands that yelt supports also have an assembly language look and feel: the names are terse and registers upon which to operate are part of the command. Commands come in 0-register, 1-register, 2-register, and 3 register variants. Yelt commands should usually be terminated by ;'s. Here are some quick examples: a01; p3; A98; x34; q3 stuff; L9; l1; A19; Note: for 1-register commands, if the register is 0, you can leave it out: the command, 'p;', prints register 0. Simple Commands: Note that variable numbers listed below are just examples There are 10 variables available for any use. They are numbered 0-9. n -- read the next line of input into variable 0. If end of file, get out of the current loop. n3 -- read the next line of input into variable 3 R4[d] [f]-- read an entire file into a register. The register must be specified immediately after the letter R. The file's name can be specified in either of two ways -- either as a second register number or as a separate token in the command ([f]). The entire file will be read into the register variable with embedded new line characters. Use SC, SR, or SW to split it up -- if needed. If no filename is specified -- either as a second register number or as a filename, then stdin will be read. p -- print variable 0 p2 -- print variable 2 a01 -- copy variable 0 into variable 1 A01 -- append variable 0 into variable 1 x49 -- swap variables 4 and 9 q9 X -- copy string 'X' into variable 9 (note: to inject ; use \;). ; is the terminator leading and trailing blanks are removed so use \s to force spaces. l3 -- put the current line number into variable 3 L9 -- put the current file name in variable 9 j3 W -- justify variable 3 to the left for a width of W J1 W -- justify variable 1 to the right for a width of W +8 -- increment variable 8 -3 -- decrement variable 3 M9! -- map variable 9 through the table defined by the -M option That is, convert variable 9 into its mapped value. The ! is optional and means the following: if there is no mapping found, leave the variable alone. t4 -- expands tabs in variable 4 SW012 =+@ -- splits variable 0 into three parts, keeping the left side in variable 0 and moving the right hand side into variable 2. The character from the delimiter list, '=', '+', or '2' will be left in register variable 1. The =+@ characters are a string whose contents defines delimiters on which the split occurs. The delimiter actually found is removed in the process and does not appear in variable 1. To use space as a delimiter, use \s. SC94 10 -- similar to the SW command but splits based on character counts. Variable 9 is reduced in size to the first 10 characters, and the deleted characters are moved into variable 4. SR012 /r/-- split the string in variable 0 into 3 pieces: the part up to but not including the regular expression, r is left in register 0. the part that matched the expression is stored in register1 the part after the match is left in register 2 c2 20-39 -- cuts out all the data in variable 2 except for the text in columns 20 through 39, inclusive. Column 20 then becomes column 1. W75 -- write the contents of variable 7 to the file whose name is found in variable 5. String substitutions: s/a/b/g -- substitute in variable 0, all a's with b' s/c/d/1 -- substitute only the first c with d in variable 0 s3/e/f/g -- substitute all e's in variable 3 with f's Note: The first string in a substitution is a grep style regular expression: meaning that you must use \( ... \), not ( ... ), for grouping. You must use \+, not just + to force at least one repetition and \ escapes almost everything else. The second string in substitution command is mostly just plain text, but you can use the following special sequences: & means the entire text pattern matching the regular expresion. \0 is the same as & \1-9 refers to the part of the source text that matched a \( \) in the regular expression. The number is the count of \('s from the beginning of the regex (starting with 1. \& injects & into the output \~0-9 injects the contents of variable 0-9 into the output. Other delimiters besides / can be used in the s command, they are: | : # ? To insert control codes or special characters into the output using a substitution, use one of the following escape sequences in the RHS of the substitution: \n -- newline \t -- tab \s -- space \b -- backspace \a -- bel \r -- carriate return \e -- escape Conditions and program control: {cmd ; cmd} -- execute multiple commands in a block if /r/ c [else x] -- if regex matches, execute cmd c, else executed command x w{ cmds } -- repeatedly execute cmds until end of file use 'n' or 'b' or 'd' to getout of the loop. b -- break out of the while loop you are in d -- continue with the loop but skip the rest of current iteration thereof Q -- quit the entire script 1,5cmd -- execute cmd only in lines 1 through 5 40,$ cmd -- execute cmd on all lines 40 and higher 20,/r/ cmd -- execute cmd on lines after 20 until the line containing /r/ -- inclusive /stuff/cmd -- execute cmd only if variable 0 contains stuff /r/,/s/ cmd -- execute cmd if curline in range /r/ to /s/ where r and s are regular expressions defining a group of lines. The line containing /s/ is executed unless the cmd checks for that and doesn't execute. For example: /r/, /s/ { /s/! cmd; } /r/ and /s/ apply to the same variable (defined in /r/~[digit]) /r/,90 cmd -- execute cmd on lines starting with the first line to contain /r/ until line 90 -- inclusive /r/,$ cmd -- execute cmd on all lines after the first containing /r -- inclusive. /x/!cmd -- execute cmd only if variable 0 does no have x in it /y/~3cmd -- execute cmd only if varible 3 has a y in it /z/~4!cmd -- execute cmd only if variale 4 has no z's in it F3 {script} -- Open the file whose name is in variable3 and apply the script to it -- you must use the n and p commands in the script if you want actually process the text. |31!cmd -- execute cmd if the text in variable 1 matches the regex stored in variable 3. The ! is optional and if given it means that the command will execute if the current line does NOT match the regex in var 3. Functions C fun 1,3; -- Call function 'fun' passing registers 1 and 3 to that function which will use them as its registers 0 and 1 then return any data to the caller back in the caller's registers 1 and 3. Def fun 2; -- Declare function 'fun' which accepts 2 registers as parameters and which will return any values in those same registers. See the function's comments.