One way of using eval, is to use an external command to set variables that you do not know the name of beforehand. Or a GROUP of variables. A common use of this, is to set terminal-size variables on login:
eval `resize`
Technically, the second one is the POSIX-preferred one.echo This is the uptime: `uptime` echo This is the uptime: $(uptime)
In addition to creating dynamic output, this is also very useful for setting variables:
datestring=`date` echo "The current date is: $datestring"
ksh has a builtin printf function, which many people may be familiar with from other languages such as C. The expected modifiers mostly apply. However, ksh has an extra modifier: "%T".
"%T" is related to Time output. It gives ksh a built-in "date" like function, except it's even more flexible. It can deal with unixseconds, and it can PARSE dates, in addition to outputting them.
It has many options, and a special relation to keyword "now". It has two forms of syntax:
A) %T # default 'date' type output B) %(%date%modifiers%here)T # modifiers that 'date' takesFor instance:
### print current time in normal format $ printf "%T\n" now Sat Aug 24 14:22:22 GMT 2019 ### print current time in unixseconds $ printf "%(%s)T\n" now 1566656615It does follow the printf convention of using "%" format placeholders, and thus needs an additional argument to printf to format. In the above examples, we used the special keyword argument of "now". However, you can specify other times. ksh gives you a lot of flexibility in how to specify it. Here are just a few examples.
Print out date from unixseconds number (note mandatory '#' and quotes around the number)
$ printf "%T\n" "#1566656615" Sat Aug 24 14:52:17 GMT 2019Use of relative verbal time
$ printf "%T\n" "tomorrow at noon" Sun Aug 25 12:00:00 GMT 2019 $ printf "%T\n" "a week ago" Mon Apr 15 00:00:00 GMT 2019Parse verbal time, in standard form and relative form.
$ printf "%(%a)T\n" "final day june 2001" Sat $ printf "%(%s)T\n" "Sat Aug 24 14:52:17 GMT 2019" 1566656615
Some people may be familiar with the "curses" library. It is a way to manipulate and move around text on a screen, reguardless of what kind of "terminal" the user is using.
As mentioned, this is a potentially huge topic. So, I'm just going to give you a trivial example, and say "Go read the man-page on tput". Well, okay, actually, you have to read the "tput" manpage, AND either the "terminfo" or "termcap" manpage to figure out what magical 3-5 letter name to use. For example, it should tell you that "cup" is short for the "cursor_address" command. But you must use "cup", NOT "cursor_address", with tput.
The above example clear the screen, prints the given line at a SPECIFIC place on the screen, then puts the cursor back down near the bottom of the screen for you.tput init tput clear tput cup 3 2 print -n "Here is a clean screen, with these words near the top" endline=`tput cols` tput cup $(($endline - 2)) print "and now, back to you" sleep 2
PS: If you've been doing a lot of funky things with the screen, you might want to do a
as the last thing before your shellscript exits.tput reset
This will print out a mini-menu like the following:select word in one two three exit; do echo word is $word echo reply is $REPLY if [[ "$word" = "exit" ]] ; then break; fi done
1) one 2) two 3) three 4) exit #?
Note that this will loop between "do ... done" until you trigger a break somehow! (or until the user control-c's or whatever). So dont forget an exit condition!
Here is a trivial example that just opens up a connection to an SMTP server. Note that the connection is half-duplex: You do NOT see data that you send to the other side.
#!/bin/ksh -p MAILHOST=127.0.0.1 exec 3<>/dev/tcp/$MAILHOST/25 || exit 1 read -r BANNER <&3 echo BANNER is $BANNER print -u3 HELO myhost.com read -r REPLY <&3 echo REPLY is $REPLY
The output will look something like the following:
BANNER is 220 yourhost.domain.com ESMTP Sendmail 8.11.6+Sun/8.11.6; Tue, 3 Dec 2002 17:30:01 -0800 (PST) REPLY is 250 yourhost.domain.com Hello localhost [127.0.0.1], pleased to meet you
Note that we use the "-r" flag to read. In this particular example, it is not neccessary. But in the general case, it will give you the data "raw". Be warned that if the shell cannot open the port, it will kill your entire script, with status 1, automatically
You can also dump the rest of the data waiting on the socket, to whereever you like, by doing
cat <&3 >somefile
You can cut-n-paste this into your .kshrc (if you have set ENV=$HOME/.kshrc), or directly to your prompt. Please note, however, that it presumes you have "emacs mode" enabled, otherwise it may not work properly:
Sadly, for ksh93, the process is a bit messier, involving 'keybind' commands:set -o emacs alias __A=`echo "\020"` # up arrow == ^p == back a command alias __B=`echo "\016"` # dn arrow == ^n == down a command alias __C=`echo "\006"` # rt arrow == ^f == forward a character alias __D=`echo "\002"` # lft arrow == ^b == back a character alias __H=`echo "\001"` # home == ^a == start of line
#ksh93 and later... # put this in your kshrc set -o emacs typeset -A Keytable trap 'eval "${Keytable[${.sh.edchar}]}"' KEYBD function keybind # key action { typeset key=$(print -f "%q" "$2") case $# in 2) Keytable[$1]=' .sh.edchar=${.sh.edmode}'"$key" ;; 1) unset Keytable[$1] ;; *) print -u2 "Usage: $0 key [action]" ;; esac } keybind $'\E[D' $'\002' keybind $'\E[C' $'\006' keybind $'\E[B' $'\016' keybind $'\E[A' $'\020' keybind $'\t' $'\E\E'