## ## ===== Selecting and arranging rows and columns ===== ## row (select): keep the rows that match a condition. Column names work like awk variables. $ row 'Cost > 5' < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 3 5 8.00 40.00 clamps 6 89 14.75 1312.75 bunsen burners 7 5 175.00 875.00 scales $ rdb select 'Description ~ /gloves/' < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 1 3 5.00 15.00 rubber gloves ## column (project): pick columns in any order; a name that does not exist becomes a new empty column $ column Description Cost < inventory Description Cost ----------- ---- rubber gloves 5.00 test tubes 0.50 clamps 8.00 plates 1.98 cleaning cloth 2.45 bunsen burners 14.75 scales 175.00 $ project Item Notes < owners Item Notes ---- ----- 1 3 6 ## column -d: keep all columns except the named ones (a deletion) $ column -d Cost Value < inventory Item Amount Description ---- ------ ----------- 1 3 rubber gloves 2 100 test tubes 3 5 clamps 4 23 plates 5 99 cleaning cloth 6 89 bunsen burners 7 5 scales $ subtotal Date Debit Credit < journal | column -d Account Description Date Debit Credit ---- ----- ------ 861222 25000 25000 861223 10000 10000 861224 30000 30000 ## sorttable: -n numeric, -r reverse, -f fold case $ sorttable -nr Cost < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 7 5 175.00 875.00 scales 6 89 14.75 1312.75 bunsen burners 3 5 8.00 40.00 clamps 1 3 5.00 15.00 rubber gloves 5 99 2.45 242.55 cleaning cloth 4 23 1.98 45.54 plates 2 100 0.50 50.00 test tubes ## compute: calculate columns from other columns (the new column must exist, so make it with addcol) $ addcol Total < inventory | compute 'Total = Amount * Cost' | column Item Total Item Total ---- ----- 1 15 2 50 3 40 4 45.54 5 242.55 6 1312.75 7 875 $ compute 'Value = sprintf("%5.2f", Cost * Amount)' < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 1 3 5.00 15.00 rubber gloves 2 100 0.50 50.00 test tubes 3 5 8.00 40.00 clamps 4 23 1.98 45.54 plates 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners 7 5 175.00 875.00 scales ## addcol / rename $ addcol Supplier < owners Item Owner Supplier ---- ----- -------- 1 ann 3 bob 6 cy $ rename Owner Person < owners Item Person ---- ------ 1 ann 3 bob 6 cy ## number / Number: number the rows (number: rows only, Number: rows and the head) $ number < owners number Item Owner ------ ---- ----- 1 1 ann 2 3 bob 3 6 cy $ Number < owners Number Item Owner ------ ---- ----- 1 1 ann 2 3 bob 3 6 cy ## record: print one record. 0 and 1 are the first row, 3 the third, -1 the last, -2 the one before $ record 3 < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 3 5 8.00 40.00 clamps $ record 0 < owners Item Owner ---- ----- 1 ann $ record -1 < owners Item Owner ---- ----- 6 cy $ record -2 < owners Item Owner ---- ----- 3 bob ## beyond the end: an empty table; not a number: an error $ record 9 < owners Item Owner ---- ----- $ record abc < owners record: 'abc' is not a record number (1, 2, 3 ... or -1 for the last) ## rmblank: drop empty rows; headon / headoff: add or strip the head $ column Item Cost < inventory | rmblank Item Cost ---- ---- 1 5.00 2 0.50 3 8.00 4 1.98 5 2.45 6 14.75 7 175.00 $ headoff < colors black blue carmel green purple red silver white $ headoff < colors | headon Hue Hue --- black blue carmel green purple red silver white $ printf 'a\tb\n1\t2\n' | insertdash a b - - 1 2 ## splittable: cut a table horizontally into pieces of n rows (writes colorsaa, colorsab ...) $ splittable -3 colors ; ls colors* ; cat colorsab colors colorsaa colorsab colorsac Colors ------ green purple red ## ===== Combining tables ===== ## jointable: join on the first column; -a keeps unmatched rows, -j names the key columns $ jointable inventory owners Item Amount Cost Value Description Owner ---- ------ ---- ----- ----------- ----- 1 3 5.00 15.00 rubber gloves ann 3 5 8.00 40.00 clamps bob 6 89 14.75 1312.75 bunsen burners cy $ jointable -a inventory owners Item Amount Cost Value Description Owner ---- ------ ---- ----- ----------- ----- 1 3 5.00 15.00 rubber gloves ann 2 100 0.50 50.00 test tubes 3 5 8.00 40.00 clamps bob 4 23 1.98 45.54 plates 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners cy 7 5 175.00 875.00 scales $ jointable -j1 Parent -j2 Name parent female Parent Child ------ ----- Sally Fred ## union / intersect / difference $ union expense carexpense Date Amount Account Ref Description ---- ------ ------- --- ----------- 820107 14.00 meal v meal with jones 820113 101.62 car v car repairs 820114 81.80 insur c car insurance allstate 820113 101.62 car v car repairs 820114 81.80 insur c car insurance allstate 820114 93.00 car c car registration dmv $ intersect female male Name ---- $ difference female male Name ---- Jane Sally ## paste.rdb: put tables side by side $ paste.rdb female male Name Name ---- ---- Jane Fred Sally Mike ## ===== Statistics: one result row per column ===== $ total Amount Value < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 324 2580.84 $ mean Cost < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 29.67 $ maximum Cost < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 175.00 $ minimum Cost < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 0.50 $ width < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 4 6 6 7 14 $ precision Cost < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 2 $ datatype -l < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 1 3 5.00 15.00 rubber gloves 2 100 0.50 50.00 test tubes 3 5 8.00 40.00 clamps 4 23 1.98 45.54 plates 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners 7 5 175.00 875.00 scales ---- ------ ---- ----- ----------- 0 0 2 2 -1 $ widest < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 4 6 6 7 14 $ subtotal Date Debit Credit < journal Date Account Debit Credit Description ---- ------- ----- ------ ----------- 861222 25000 25000 861223 10000 10000 861224 30000 30000 $ dbdict < inventory field name ----- ---- 1 Item 2 Amount 3 Cost 4 Value 5 Description $ schema inventory owners Table Field Name ----- ----- ---- inventory 1 Item inventory 2 Amount inventory 3 Cost inventory 4 Value inventory 5 Description owners 1 Item owners 2 Owner $ tableorlist inventory maillist table list ## ===== Checking and displaying ===== $ check.rdb < inventory $ printf 'a\tb\n-\t-\n1\t2\t3\n4\n' | check.rdb check.rdb: Columns (3) do not equal headline columns (2) in row 1 (line 3). 1 2 3 check.rdb: Columns (1) do not equal headline columns (2) in row 2 (line 4). 4 $ display < owners Item Owner ---- ----- 1 ann 3 bob 6 cy $ see < owners Item^IOwner$ ----^I-----$ 1^Iann$ 3^Ibob$ 6^Icy$ $ validate 'Cost > 40 { print "expensive:", Description }' < badinventory Item# Onhand Cost Value Description ----- ------ ---- ----- ----------- expensive: rubber gloves 1 3 50 150 rubber gloves expensive: test tubes 2 100 X 500 test tubes expensive: clamps 3 -5 80 -400 clamps 4 23 19 437 plates 5 -99 24 -2376 cleaning cloth $ column Colors < orders | domain colors Colors ------ farble yellow $ domain colors black x x ## fd: does Description depend on Item? (prints true/false) $ fd Item Description < inventory true $ fd Description Cost < inventory true ## ===== Text tools (arguments or standard input) ===== $ justify < inventory Item Amount Cost Value Description ---- ------ ------ ------- -------------- 1 3 5.00 15.00 rubber gloves 2 100 0.50 50.00 test tubes 3 5 8.00 40.00 clamps 4 23 1.98 45.54 plates 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners 7 5 175.00 875.00 scales $ justify -r Description < inventory Item Amount Cost Value Description ---- ------ ---- ----- -------------- 1 3 5.00 15.00 rubber gloves 2 100 0.50 50.00 test tubes 3 5 8.00 40.00 clamps 4 23 1.98 45.54 plates 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners 7 5 175.00 875.00 scales $ justify -c Cost < inventory Item Amount Cost Value Description ---- ------ ------ ----- ----------- 1 3 5.00 15.00 rubber gloves 2 100 0.50 50.00 test tubes 3 5 8.00 40.00 clamps 4 23 1.98 45.54 plates 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners 7 5 175.00 875.00 scales $ trim < inventory Item Amount Cost Value Description ---- ------ ------ ------- -------------- 1 3 5.00 15.00 rubber gloves 2 100 0.50 50.00 test tubes 3 5 8.00 40.00 clamps 4 23 1.98 45.54 plates 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners 7 5 175.00 875.00 scales $ compresss < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 1 3 5.00 15.00 rubber gloves 2 100 0.50 50.00 test tubes 3 5 8.00 40.00 clamps 4 23 1.98 45.54 plates 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners 7 5 175.00 875.00 scales $ pad -4 < owners Item Owner ---- ----- 1 ann 3 bob 6 cy $ printf 'hello world\n' | cap Hello World $ uppercase hello world HELLO WORLD $ lowercase HELLO WORLD hello world $ printf 'one two\n' | uppercase ONE TWO $ substitute gloves mittens colors ; cat colors Colors ------ black blue carmel green purple red silver white $ trimblank ' padded ' padded $ padstring 8 abc abc $ padstring -8 abc abc $ length 'how long?' 9 $ filesize inventory 263 $ ascii aA1 97 65 49 $ ascii ' ' 32 $ chr 72 105 Hi $ word < ed.t Deutch English I Ich dich liebe love widgit you $ cap < ed.t English Deutch ------- ------ I Ich Love Liebe You Dich Widgit $ blank < maillist Number Name Company Street City State ZIP Phone Number Name Company Street City State ZIP Phone $ printf 'a\n' | prompt 'prompt text' prompt text $ not false && echo 'false failed, so not succeeded' false failed, so not succeeded $ path ls > /dev/null && echo 'ls found on the path' ls found on the path ## tabletom4 / tabletosed make translation files from ed.t; translate applies them $ tabletom4 < ed.t define(I,Ich) define(love,liebe) define(you,dich) $ tabletosed < ed.t s/I/Ich/g s/love/liebe/g s/you/dich/g $ tabletom4 < ed.t > ed ; echo 'I love you.' | translate ed Ich liebe dich. ## uniondict builds the ed define-file out of ed.low and ed.allcap $ printf 'English\tDeutsch\n-------\t-------\nlove\tliebe\n' > ed.low ; printf 'English\tDeutsch\n-------\t-------\nLOVE\tLIEBE\n' > ed.allcap ; uniondict ed define(love,liebe) define(Love,Liebe) define(LOVE,LIEBE) ## ===== Conversions ===== $ tabletolist < owners Item 1 Owner ann Item 3 Owner bob Item 6 Owner cy $ tabletolist -l < owners Item 1 Owner ann Item 3 Owner bob Item 6 Owner cy $ tabletolist < owners | listtotable Item Owner ---- ----- 1 ann 3 bob 6 cy $ listtotable < maillist Number Name Company Street City State ZIP Phone ------ ---- ------- ------ ---- ----- --- ----- 1 Ronald McDonald McDonalds 123 Mac Attack Memphis TENN 30000 (111) 222-3333 2 Chiquita Banana United Brands Uno Avenido de la Reforma San Jose Costa Rica 123456789 1234 $ listtosh < maillist Number='1' Name='Ronald McDonald' Company='McDonalds' Street='123 Mac Attack' City='Memphis' State='TENN' ZIP='30000' Phone='(111) 222-3333' Number='2' Name='Chiquita Banana' Company='United Brands' Street='Uno Avenido de la Reforma' City='San Jose' State='Costa Rica' ZIP='123456789' Phone='1234' $ tabletofix Item=4 Owner=6r < owners 1 ann 3 bob 6 cy $ tabletofix Item=4 Owner=6r < owners | fixtotable Item=1,4 Owner=5,6 Item Owner ---- ----- 1 ann 3 bob 6 cy $ tabletostruct tag owners < owners struct tag { char *Item; char *Owner; } owners [] = { "1","ann" }, { "3","bob" }, { "6","cy" } ; $ tabletotbl < owners .TS n l. Item Owner _ 1 ann 3 bob 6 cy .TE $ tabletofact parent parent(Sally,Fred). parent(Mike,Fred). parent(Fred,Jane). $ tabletorule ruletable mother(X,Y) :- female(X), parent(X,Y). ## ===== Dates ===== ## julian: dates to day numbers (arithmetic); gregorian: back again (-e European, -u US, -c day count) $ julian Date < journal Date Account Debit Credit Description ---- ------- ----- ------ ----------- 1752827 101 25000 cash from loan 1752827 211.1 25000 loan number #378-14 Bank Amerigold 1752828 150.1 10000 test equipment from Zarkoff 1752828 101 5000 cash payment 1752828 211.2 5000 note payable to Zarkoff Equipment 1752829 130 30000 inventory - parts from CCPSC 1752829 201.1 15000 accounts payable to CCPSC 1752829 101 15000 cash payment to CCPSC for parts $ julian Date < journal | gregorian Date Date Account Debit Credit Description ---- ------- ----- ------ ----------- 861222 101 25000 cash from loan 861222 211.1 25000 loan number #378-14 Bank Amerigold 861223 150.1 10000 test equipment from Zarkoff 861223 101 5000 cash payment 861223 211.2 5000 note payable to Zarkoff Equipment 861224 130 30000 inventory - parts from CCPSC 861224 201.1 15000 accounts payable to CCPSC 861224 101 15000 cash payment to CCPSC for parts $ julian Date < journal | gregorian -e Date Date Account Debit Credit Description ---- ------- ----- ------ ----------- 22/12/86 101 25000 cash from loan 22/12/86 211.1 25000 loan number #378-14 Bank Amerigold 23/12/86 150.1 10000 test equipment from Zarkoff 23/12/86 101 5000 cash payment 23/12/86 211.2 5000 note payable to Zarkoff Equipment 24/12/86 130 30000 inventory - parts from CCPSC 24/12/86 201.1 15000 accounts payable to CCPSC 24/12/86 101 15000 cash payment to CCPSC for parts ## computedate: a date plus n days $ computedate 890331 45 890515 $ computedate 891231 1 900101 $ test $(todaysdate | wc -c) -eq 7 && echo 'todaysdate prints YYMMDD' todaysdate prints YYMMDD ## ===== Names that sound alike ===== $ soundex < name Name Soundex ---- ------- Abraham A165 Abraham A165 Adams A352 Ackerman A265 Manis M520 Mann M500 Miller M460 Moon M500 ## like: names that sound like Mann (needs the soundex table name.x, sorted by Soundex) $ soundex < name > name.x ; like Mann name Name ---- Mann Moon $ hashkey 11 ABCD 2 $ hashkey 29 abcdefg 4 ## ===== Fast access: index, search, seek ===== ## search without an index scans the table (-ms); keys come from stdin $ echo scales | search inventory Description Item Amount Cost Value Description ---- ------ ---- ----- ----------- 7 5 175.00 875.00 scales ## -h leaves out the head line of the answer $ printf 'Description\n-----------\nscales\n' | search -h inventory Description 7 5 175.00 875.00 scales ## build indexes in each method: b binary, r record, i inverted, h hash $ index -mr inventory ; ls inventory.r ; echo 3 | search -mr inventory inventory.r Item Amount Cost Value Description ---- ------ ---- ----- ----------- 3 5 8.00 40.00 clamps $ index -mi inventory Description ; ls inventory.i ; echo cl | search -mi -x inventory Description inventory.i Item Amount Cost Value Description ---- ------ ---- ----- ----------- 3 5 8.00 40.00 clamps 5 99 2.45 242.55 cleaning cloth $ index -mh inventory Item ; ls inventory.h ; echo 5 | search -mh inventory Item inventory.h Item Amount Cost Value Description ---- ------ ---- ----- ----------- 5 99 2.45 242.55 cleaning cloth ## seek: where does the row start and end? (byte offsets) $ echo 5 | seek inventory Item 172 204 0 8 $ echo 5 | seek -mh inventory Item 172 204 104 113 ## searchtree: is Sally an ancestor of Jane? (needs a table of Parent, Child) $ searchtree parent Sally Jane Parent Child TRUE ## vindex: look-up tables for ve $ vindex owners Item : Owner ; vindex owners == Item-A Item ---- 1 3 6 == Item-B Item Owner ---- ----- 1 ann 3 bob 6 cy $ tableorlist owners maillist table list ## ===== Changing tables: append, replace, delete, enter ===== ## append adds a row and updates the indexes ## -h: the new row has no head line $ printf '8\t1\t1.00\t1.00\tnew thing\n' | append -h -mh inventory Item ; echo 8 | search -mh inventory Item Item Amount Cost Value Description ---- ------ ---- ----- ----------- 8 1 1.00 1.00 new thing ## replace overwrites bytes from..to; take the offsets from seek $ set -- $(echo 3 | seek inventory Item) ; printf '3\t6\t8.00\t48.00\tclamps\n' | replace inventory $1 $2 ; echo 3 | search inventory Item Item Amount Cost Value Description ---- ------ ---- ----- ----------- 3 6 8.00 48.00 clamps ## delete blanks the row and fixes the index $ echo 4 | delete -mh inventory Item ; echo 4 | search -mh inventory Item ; echo 5 | search -mh inventory Item Item Amount Cost Value Description ---- ------ ---- ----- ----------- Item Amount Cost Value Description ---- ------ ---- ----- ----------- 5 99 2.45 242.55 cleaning cloth ## enter reads rows field by field from the terminal; -1 means one row $ printf '9\n2\n3\n4\nnewer thing\n' | enter -1 inventory > /dev/null $ tail -1 inventory 9 2 3 4 newer thing ## lock / unlock: the second process may not lock the same bytes $ lock inventory 111 10 20 0 0 ; echo "first lock status $?" first lock status 0 $ lock inventory 222 15 25 0 0 ; echo "second lock status $?" lock: inventory: bytes 15-25 are locked by process 111 second lock status 1 $ unlock inventory 111 10 20 0 0 ; echo "unlock status $?" unlock status 0 $ lock inventory 222 15 25 0 0 ; echo "second lock now status $?" ; unlock inventory 222 15 25 0 0 second lock now status 0 ## vilock edits a table under a lock; update.rdb edits records interactively $ echo | vilock inventory ; echo "vilock status $?" vilock status 0 ## update.rdb with a key on stdin and no changes (an empty line ends the dialog) $ printf '3\n\n' | update.rdb inventory Item | head -8 > -- record 3 of 8 1 Item 3 2 Amount 6 3 Cost 8.00 4 Value 48.00 5 Description clamps > -- record 4 of 8 1 Item 5 ## ve is a line editor in this version $ printf 'q\n' | ve inventory | head -3 -- inventory: record 1 of 9 1 Item 1 2 Amount 3 ## ===== Reports and forms ===== ## report fills a form with the fields of each list record () $ cat form < City >, Hi < Name >: $ report form < maillist Ronald McDonald McDonalds 123 Mac Attack Memphis, TENN 30000 Hi Ronald McDonald: Chiquita Banana United Brands Uno Avenido de la Reforma San Jose, Costa Rica 123456789 Hi Chiquita Banana: ## label prints mailing labels, letter prints form letters $ label < maillist Ronald McDonald McDonalds 123 Mac Attack Memphis, TENN 30000 Chiquita Banana United Brands Uno Avenido de la Reforma San Jose, Costa Rica 123456789 $ letter form < maillist | head -5 Ronald McDonald McDonalds 123 Mac Attack Memphis, TENN 30000 ## screen turns a form into a shell script that asks for the fields. Use a form with labels ## and every column once (entry); the report template `form` would give a blank, doubled screen. ## Run the script with: CLEAR=$(clear.rdb) sh script > table 2>&1 (the table goes to stderr) $ cat entry Mail List Entry Form Name : Company: Street: City : State : ZIP: Phone : [Speichern] [Abbrechen] $ screen < entry : paint crt screen exec 1>/dev/tty cat <&2 echo "Name Company Street City State ZIP Phone" echo "---- ------- ------ ---- ----- --- -----" : append row echo "$Name $Company $Street $City $State $ZIP $Phone" ## mask draws the form itself (fields, buttons, frame) and writes the row as a table on stdout. ## It needs a terminal, so here only the picture of the form and its fields (-s) is shown. ## Try it: mask -b < maskform mask < maskform | append -h t $ cat maskform Mail List Entry Name : Company: Street : City : State: ZIP: Phone : [ Save ] [ Cancel ] $ mask -s -b < maskform ┌──────────────────────────────────────────────────────────────┐ │ Mail List Entry │ │ │ │ Name : ________________________ │ │ Company: ________________________ │ │ Street : ________________________ │ │ City : ________________ State: __________ ZIP: _________ │ │ Phone : ________________ │ │ │ │ [ Save ] [ Cancel ] │ └──────────────────────────────────────────────────────────────┘ Fields: Name row 4 col 12 width 24 Company row 5 col 12 width 24 Street row 6 col 12 width 24 City row 7 col 12 width 16 State row 7 col 37 width 10 ZIP row 7 col 54 width 9 Phone row 8 col 12 width 16 [Save] row 10 col 6 [Cancel] row 10 col 17 (cancels) ## reportwriter: a sample report with page headings (the date is cut out) $ reportwriter -3 Prices < inventory | grep -v 'Report Date' Prices Item Amount Cost Value Description ---- ------ ---- ----- ----------- 1 3 5.00 15.00 rubber gloves 2 100 0.50 50.00 test tubes 3 6 8.00 48.00 clamps Page 1 Prices Item Amount Cost Value Description ---- ------ ---- ----- ----------- 5 99 2.45 242.55 cleaning cloth 6 89 14.75 1312.75 bunsen burners Page 2 Prices Item Amount Cost Value Description ---- ------ ---- ----- ----------- 7 5 175.00 875.00 scales 8 1 1.00 1.00 new thing 9 2 3 4 newer thing Page 3 ## tabletom4 / tabletosed / tabletostruct were shown above ## ===== Help and the terminal ===== $ rdb --version rdb 0.7.0 $ howmany 136 $ whatis row row - make a new table where rows match logical condition row row 'column condition column-or-value ..' < table $ whatwill total foot - foot or subtotal Debits and Credit of ledger foot foot subtotal - output subtotals of columns in a table subtotal subtotal [ -l ] [ break-column column ... ] < table total - sum a column total total [ -l ] [ column ... ] < table w2 - produce W-2 totals per employee from ledgerpay w2 w2 $ helpme Command Description ------- ----------- "menu" a menu with some commands "rdb" a list of the available commands "commands" description and syntax of all the commands "whatis command" description and syntax of command "whatwill feature" info on commands with that feature "rdb man command" the manual page for that command $ commands | head -5 Command Description Syntax ------- ----------- ------ Number Insert a column-row number into a table or list < tableorlist act List all /act commands addcol Add a column to a table newcolumn < table $ man -g column | head -12 column() column() column [ Column ... ] < tableorlist The command column reads tableorlist and writes a new table (or list) that consists of each Column, in the order you list them on the command line. If you give a column name that is not one of the columns for tableorlist, column creates a new column with that name, in that location, and leaves it empty. This lets you to create new columns. If you want to compute a col‐ umn that does not exist, use this column facility to create it, then use the compute command to compute it. However, if you misspell a column name, $ termput cl | cat -v ^[[H^[[2J $ termput cm | cat -v ^[[%i%d;%dH $ tset vt100 | head -3 :cl=\e[H\e[2J:ho=\e[H:ce=\e[K:cd=\e[J:cm=\e[%i%d;%dH:so=\e[7m:se=\e[m:us=\e[4m:ue=\e[m:mb=\e[5m:md=\e[1m:me=\e[m:as=\e(0:ae=\e(B:up=\e[A:do=\e[B:bs=\b:co#80:li#24:tc=vt100: $ cursor 3 8 | cat -v ^[[3;8H $ clear.rdb | cat -v ^[[H^[[2J $ rmcore ; echo "rmcore status $?" rmcore status 0 $ mkdir t1 ; cp owners t1 ; cpdir.rdb t1 t2 ; ls t2 owners $ menu < /dev/null | head -3 Number Name For ------ ---- --- 0 exit leave menu or return to higher menu $ timesearch > /dev/null ; echo "timesearch status $?" timesearch status 0 $ testsearch | tail -3 -mh: ok (200 rows found) -mi: ok (200 rows found) -mr: ok (200 rows found) $ act act adjust balance bom calcpay calculate cashflow chartdup close consolidate cstate explode fillform foot getjournal invoice sale tax update.inv w2 ## ===== /act: a small accounting system ===== ## (the commands work on tables in the current directory; NEXTDATE fixes the date they use) $ act act adjust balance bom calcpay calculate cashflow chartdup close consolidate cstate explode fillform foot getjournal invoice sale tax update.inv w2 ## cashflow: compute the Balance column of a cash table $ cashflow < cash Date Amount Balance Description ---- ------ ------- ----------- 890101 512 512 current balance 890101 -450 62 rent check 890101 1000 1062 pay check 890115 -300 762 estimated tax payment ## tax: look up the tax for an income in a tax table $ tax 20000 < X83 3369 ## tax also works with the real 2026 tables of DE, AT, CH (federal tax only) and LI (Landessteuer, ## before the municipal surcharge of 150 % to 250 %); see README. Tax on an income of 60000: $ tax 60000 < taxDE2026 14233 $ tax 60000 < taxAT2026 15447 $ tax 60000 < taxCH2026 671 $ tax 60000 < taxLI2026 1396 ## Swiss cantons (einfache Staatssteuer, single; still times the cantonal Steuerfuss, plus Gemeinde): AI AR SG GR $ tax 60000 < taxCH_AI2026 3770 $ tax 60000 < taxCH_AR2026 1065 $ tax 60000 < taxCH_SG2026 3344 $ tax 60000 < taxCH_GR2026 3748 ## explode: parts list -> all subparts with counts (part, amount) $ explode 10001 2 parttable Part Amount ---- ------ 10001 2 10010 6 10020 8 10100 52 ## chartdup: look for duplicate account numbers and short names in chart $ printf 'Account\tShort\n-------\t-----\n1\ta\n1\tb\n2\ta\n' > chart ; chartdup Duplicate Account numbers in chart. See chart.Account 1 a 1 b Duplicate Short names in chart. See chart.Short 1 a 2 a ## foot: subtotals of Debit and Credit per account in the ledger $ foot Account Date Debit Credit ------- ---- ----- ------ 101 820102 25000 101 820103 5000 101 820104 15000 ------- ---- ----- ------ 101 15000 30000 130 820104 30000 ------- ---- ----- ------ 130 30000 0 150.1 820103 10000 ------- ---- ----- ------ 150.1 10000 0 201.1 820104 15000 ------- ---- ----- ------ 201.1 15000 0 211.1 820102 25000 ------- ---- ----- ------ 211.1 0 25000 211.2 820103 5000 ------- ---- ----- ------ 211.2 0 5000 ## adjust, balance, close: need a trial balance and an adjusting journal $ printf 'Account\tDebit\tCredit\tFormat\tTaxline\tShort\tName\n-------\t-----\t------\t------\t-------\t-----\t----\n1010\t11178\t\tB-A\t4L01\tcash\tCash\n3010\t\t13500\tI-I\t101a\tsales\tSales\n' > trialbalance $ printf 'Account\tDebit\tCredit\tFormat\tTaxline\tName\n-------\t-----\t------\t------\t-------\t----\n1010\t100\t\tB-A\t4L01\tCash\n' > journaladjust $ adjust ; cat adjustedtrial Account Debit Credit Format Taxline Short Name ------- ----- ------ ------ ------- ----- ---- 1010 11278 B-A 4L01 cash Cash 3010 13500 I-I 101a sales Sales $ balance ; sed 2d balancesheet Company Balancesheet 11278 Cash ----- ------------------------ 11278 Total Assets 13500 Retained Earnings (Profit) ------ -------------------------- 13500 Total Liabilities and Equity $ NEXTDATE=870101 close ; cat journalnext Account Date Debit Credit Ref Description ------- ---- ----- ------ --- ----------- 1010 870101 11278 jl brought forward 4997 870101 11278 jl brought forward ## fillform: sum the adjusted trial balance per tax line into a tax form $ printf 'Taxline\tDescription\n-------\t-----------\n4L01\tCash on hand\n101a\tGross sales\n' > taxform.f1 $ fillform f1 ; cat f1 Taxline Amount Description ------- ------ ----------- 4L01 11278 Cash on hand 101a 13500 Gross sales ## calculate: compute columns of a form; f1.calc has one 'Column = expression' per line $ echo 'Amount = Amount * 2' > f1.calc ; calculate f1 ; cat f1 Taxline Amount Description ------- ------ ----------- 4L01 22556 Cash on hand 101a 27000 Gross sales ## getjournal / consolidate: collect subsidiary journals into the general journal $ printf 'Date\tAmount\tAccount\tRef\tDescription\n----\t------\t-------\t---\t-----------\n870101\t100\t4010\ts1\tshop sale\n' > journalsales $ NEXTDATE=870131 getjournal journalsales Date Amount Account Ref Description ---- ------ ------- --- ----------- 870131 100.00 s1 sales from journalsales $ printf 'Date\tAmount\tAccount\tRef\tDescription\n----\t------\t-------\t---\t-----------\n870102\t40\t5010\tp1\tpaper\n' > journalexpense $ rm journal ; consolidate 870131 ; cat journal Date Account Debit Credit Ref Description ---- ------- ----- ------ --- ----------- 870102 5010 40 p1 paper 870101 4010 100 s1 shop sale 870131 1010 40 double-entry 870131 1010 100 double-entry ## payroll: calcpay sorts journalpay into ledgerpay, w2 totals per employee $ printf 'Number\tGross\tFederal\tState\tNet\n------\t-----\t-------\t-----\t---\n2\t1000\t100\t50\t850\n1\t900\t90\t40\t770\n2\t1000\t100\t50\t850\n' > journalpay $ calcpay ; cat ledgerpay Number Gross Federal State Net ------ ----- ------- ----- --- 1 900 90 40 770 2 1000 100 50 850 2 1000 100 50 850 $ w2 Number Gross Federal State Net ------ ----- ------- ----- --- 1 900 90 40 770 2 2000 200 100 1700 ## ===== /act: sales and stock ===== $ printf 'Code\tName\tPrice\n----\t----\t-----\n10010\twidget\t2.50\n10020\tgadget\t10\n' > product $ printf 'Number\tCompany\tLast\n------\t-------\t----\n7\tAcme\tRoe\n' > customer ## sale: enter a sale order (customer, then code and quantity per item, then y to confirm) $ printf '7\n10010\n4\n10020\n1\n\ny\n\n' | NEXTDATE=870105 sale Enter Customer Number (? for new, /string search, Return to exit) Mailing Address for Customer Number 7 Roe Acme Code (Return when done): Qty: Code (Return when done): Qty: Code (Return when done): Number Cust Date Shipped Gross Tax Total ------ ---- ---- ------- ----- --- ----- 1 7 870105 0 20.00 1.00 21.00 Is this correct? (y, n) Enter Customer Number (? for new, /string search, Return to exit) $ cat salesorder Number Cust Date Shipped Gross Tax Total ------ ---- ---- ------- ----- --- ----- 1 7 870105 0 20.00 1.00 21.00 ## invoice / cstate: print an invoice or customer statement for what was sold $ printf '1\n\n' | invoice Please enter order number (or Return to exit): Invoice ------- Company Order Number 1 Date Ordered 870105 Date Shipped 0 Mailing Address for Customer Number 7 Roe Acme Order Number Code Backord Qty Price Total Name ----- ------ ---- ------- --- ----- ----- ---- 1 1 10010 10 4 2.50 10.00 widget 1 2 10020 10 1 10 10.00 gadget Gross 20.00 Tax 1.00 Total 21.00 Please enter order number (or Return to exit): $ printf '7\n\n' | cstate Please enter customer number (or all or Return to exit): Customer Statement ------------------ Mailing Address for Customer Number 7 Roe Acme Now Due and Payable is your balance of: 21.00 Details of Your Orders and Payments Cust Date Amount Ref ---- ---- ------ --- 7 870105 -21.00 1 -21.00 Please enter customer number (or all or Return to exit): ## bom: parts needed for everything sold (needs the table part with Code, Subpart, Count) $ printf 'Code\tSubpart\tCount\n----\t-------\t-----\n10010\ts1\t3\n10020\ts1\t1\n10020\ts2\t2\n' > part $ bom ; cat bom Code Qty ---- --- s1 13 s2 2 ## update.inv: change the stock of one item, with record locking (INV names the table) $ cp inventory inv ; printf '7\n9\n\n' | INV=inv update.inv | tail -n +2 Item Number: (or hit Return key to exit.) Item=7 Amount=5 Cost=175.00 Value=875.00 Description=scales Amount Amount: Item Number: (or hit Return key to exit.) $ grep '^7' inv 7 9 175.00 1575 scales ## ===== Choosing rows on the terminal ===== ## pick shows a table, lets you scroll, filter (/) and mark rows (Space, -m), and writes the ## chosen rows as a table, so it can sit in a pipe. It needs a terminal; -k feeds the keys instead. ## Try it: pick -m < inventory | total Amount Value ## mark the 2nd and 5th row (down, space, down, down, space) and finish with enter $ pick -m -k 'down space down down space enter' < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 2 100 0.50 50.00 test tubes 5 99 2.45 242.55 cleaning cloth ## the same chosen rows go on into total $ pick -m -k 'down space down down space enter' < inventory | total Amount Value Item Amount Cost Value Description ---- ------ ---- ----- ----------- 199 292.55 ## filter with / (type, enter), then choose the row that is left $ pick -k '/clamps enter enter' < inventory Item Amount Cost Value Description ---- ------ ---- ----- ----------- 3 6 8.00 48.00 clamps ## Esc cancels: nothing on stdout, exit status 1 $ pick -k esc < inventory ; echo "status $?" pick: nothing chosen status 1