Files
rdb/demo/testall.cmds

301 lines
13 KiB
Plaintext

# testall.cmds -- one shell command per line; `testall` runs them in a scratch copy of demo/.
# ## line is printed as a heading/explanation # line is a silent comment
# Save a known-good run: testall > testall.old later: testall | diff testall.old -
# Tables used here: inventory journal expense carexpense parent female male owners
# chart ledger parttable cash X83 colors orders ed.t maillist form name
##
## ===== 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
rdb select 'Description ~ /gloves/' < inventory
## column (project): pick columns in any order; a name that does not exist becomes a new empty column
column Description Cost < inventory
project Item Notes < owners
## column -d: keep all columns except the named ones (a deletion)
column -d Cost Value < inventory
subtotal Date Debit Credit < journal | column -d Account Description
## sorttable: -n numeric, -r reverse, -f fold case
sorttable -nr Cost < inventory
## 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
compute 'Value = sprintf("%5.2f", Cost * Amount)' < inventory
## addcol / rename
addcol Supplier < owners
rename Owner Person < owners
## number / Number: number the rows (number: rows only, Number: rows and the head)
number < owners
Number < owners
## record: print one record. 0 and 1 are the first row, 3 the third, -1 the last, -2 the one before
record 3 < inventory
record 0 < owners
record -1 < owners
record -2 < owners
## beyond the end: an empty table; not a number: an error
record 9 < owners
record abc < owners
## rmblank: drop empty rows; headon / headoff: add or strip the head
column Item Cost < inventory | rmblank
headoff < colors
headoff < colors | headon Hue
printf 'a\tb\n1\t2\n' | insertdash
## splittable: cut a table horizontally into pieces of n rows (writes colorsaa, colorsab ...)
splittable -3 colors ; ls colors* ; cat colorsab
## ===== Combining tables =====
## jointable: join on the first column; -a keeps unmatched rows, -j names the key columns
jointable inventory owners
jointable -a inventory owners
jointable -j1 Parent -j2 Name parent female
## union / intersect / difference
union expense carexpense
intersect female male
difference female male
## paste.rdb: put tables side by side
paste.rdb female male
## ===== Statistics: one result row per column =====
total Amount Value < inventory
mean Cost < inventory
maximum Cost < inventory
minimum Cost < inventory
width < inventory
precision Cost < inventory
datatype -l < inventory
widest < inventory
subtotal Date Debit Credit < journal
dbdict < inventory
schema inventory owners
tableorlist inventory maillist
## ===== Checking and displaying =====
check.rdb < inventory
printf 'a\tb\n-\t-\n1\t2\t3\n4\n' | check.rdb
display < owners
see < owners
validate 'Cost > 40 { print "expensive:", Description }' < badinventory
column Colors < orders | domain colors
domain colors black x
## fd: does Description depend on Item? (prints true/false)
fd Item Description < inventory
fd Description Cost < inventory
## ===== Text tools (arguments or standard input) =====
justify < inventory
justify -r Description < inventory
justify -c Cost < inventory
trim < inventory
compresss < inventory
pad -4 < owners
printf 'hello world\n' | cap
uppercase hello world
lowercase HELLO WORLD
printf 'one two\n' | uppercase
substitute gloves mittens colors ; cat colors
trimblank ' padded '
padstring 8 abc
padstring -8 abc
length 'how long?'
filesize inventory
ascii aA1
ascii ' '
chr 72 105
word < ed.t
cap < ed.t
blank < maillist
printf 'a\n' | prompt 'prompt text'
not false && echo 'false failed, so not succeeded'
path ls > /dev/null && echo 'ls found on the path'
## tabletom4 / tabletosed make translation files from ed.t; translate applies them
tabletom4 < ed.t
tabletosed < ed.t
tabletom4 < ed.t > ed ; echo 'I love you.' | translate ed
## 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
## ===== Conversions =====
tabletolist < owners
tabletolist -l < owners
tabletolist < owners | listtotable
listtotable < maillist
listtosh < maillist
tabletofix Item=4 Owner=6r < owners
tabletofix Item=4 Owner=6r < owners | fixtotable Item=1,4 Owner=5,6
tabletostruct tag owners < owners
tabletotbl < owners
tabletofact parent
tabletorule ruletable
## ===== Dates =====
## julian: dates to day numbers (arithmetic); gregorian: back again (-e European, -u US, -c day count)
julian Date < journal
julian Date < journal | gregorian Date
julian Date < journal | gregorian -e Date
## computedate: a date plus n days
computedate 890331 45
computedate 891231 1
test $(todaysdate | wc -c) -eq 7 && echo 'todaysdate prints YYMMDD'
## ===== Names that sound alike =====
soundex < name
## like: names that sound like Mann (needs the soundex table name.x, sorted by Soundex)
soundex < name > name.x ; like Mann name
hashkey 11 ABCD
hashkey 29 abcdefg
## ===== Fast access: index, search, seek =====
## search without an index scans the table (-ms); keys come from stdin
echo scales | search inventory Description
## -h leaves out the head line of the answer
printf 'Description\n-----------\nscales\n' | search -h inventory Description
## build indexes in each method: b binary, r record, i inverted, h hash
index -mr inventory ; ls inventory.r ; echo 3 | search -mr inventory
index -mi inventory Description ; ls inventory.i ; echo cl | search -mi -x inventory Description
index -mh inventory Item ; ls inventory.h ; echo 5 | search -mh inventory Item
## seek: where does the row start and end? (byte offsets)
echo 5 | seek inventory Item
echo 5 | seek -mh inventory Item
## searchtree: is Sally an ancestor of Jane? (needs a table of Parent, Child)
searchtree parent Sally Jane Parent Child
## vindex: look-up tables for ve
vindex owners Item : Owner ; vindex owners
tableorlist owners maillist
## ===== 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
## 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
## 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
## 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
## lock / unlock: the second process may not lock the same bytes
lock inventory 111 10 20 0 0 ; echo "first lock status $?"
lock inventory 222 15 25 0 0 ; echo "second lock status $?"
unlock inventory 111 10 20 0 0 ; echo "unlock status $?"
lock inventory 222 15 25 0 0 ; echo "second lock now status $?" ; unlock inventory 222 15 25 0 0
## vilock edits a table under a lock; update.rdb edits records interactively
echo | vilock inventory ; echo "vilock status $?"
## 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
## ve is a line editor in this version
printf 'q\n' | ve inventory | head -3
## ===== Reports and forms =====
## report fills a form with the fields of each list record (<Name>)
cat form
report form < maillist
## label prints mailing labels, letter prints form letters
label < maillist
letter form < maillist | head -5
## 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
screen < entry
## 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
mask -s -b < maskform
## reportwriter: a sample report with page headings (the date is cut out)
reportwriter -3 Prices < inventory | grep -v 'Report Date'
## tabletom4 / tabletosed / tabletostruct were shown above
## ===== Help and the terminal =====
rdb --version
howmany
whatis row
whatwill total
helpme
commands | head -5
man -g column | head -12
termput cl | cat -v
termput cm | cat -v
tset vt100 | head -3
cursor 3 8 | cat -v
clear.rdb | cat -v
rmcore ; echo "rmcore status $?"
mkdir t1 ; cp owners t1 ; cpdir.rdb t1 t2 ; ls t2
menu < /dev/null | head -3
timesearch > /dev/null ; echo "timesearch status $?"
testsearch | tail -3
act
## ===== /act: a small accounting system =====
## (the commands work on tables in the current directory; NEXTDATE fixes the date they use)
act
## cashflow: compute the Balance column of a cash table
cashflow < cash
## tax: look up the tax for an income in a tax table
tax 20000 < X83
## 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
tax 60000 < taxAT2026
tax 60000 < taxCH2026
tax 60000 < taxLI2026
## Swiss cantons (einfache Staatssteuer, single; still times the cantonal Steuerfuss, plus Gemeinde): AI AR SG GR
tax 60000 < taxCH_AI2026
tax 60000 < taxCH_AR2026
tax 60000 < taxCH_SG2026
tax 60000 < taxCH_GR2026
## explode: parts list -> all subparts with counts (part, amount)
explode 10001 2 parttable
## 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
## foot: subtotals of Debit and Credit per account in the ledger
foot
## 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
balance ; sed 2d balancesheet
NEXTDATE=870101 close ; cat journalnext
## 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
## calculate: compute columns of a form; f1.calc has one 'Column = expression' per line
echo 'Amount = Amount * 2' > f1.calc ; calculate f1 ; cat f1
## 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
printf 'Date\tAmount\tAccount\tRef\tDescription\n----\t------\t-------\t---\t-----------\n870102\t40\t5010\tp1\tpaper\n' > journalexpense
rm journal ; consolidate 870131 ; cat journal
## 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
w2
## ===== /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
cat salesorder
## invoice / cstate: print an invoice or customer statement for what was sold
printf '1\n\n' | invoice
printf '7\n\n' | cstate
## 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
## 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
grep '^7' inv
## ===== 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
## the same chosen rows go on into total
pick -m -k 'down space down down space enter' < inventory | total Amount Value
## filter with / (type, enter), then choose the row that is left
pick -k '/clamps enter enter' < inventory
## Esc cancels: nothing on stdout, exit status 1
pick -k esc < inventory ; echo "status $?"