Operating System - HP-UX
1753773 Members
6209 Online
108799 Solutions
New Discussion

ksh time prompt PS1; It works, but *why*? (ksh obfuscation?)

 
SOLVED
Go to solution
A. Daniel King_1
Super Advisor

ksh time prompt PS1; It works, but *why*? (ksh obfuscation?)

I've been looking at a current, continuously updated time prompt in ksh, similar to:

http://forums.itrc.hp.com/cm/QuestionAnswer/1,,0xa0ead211e18ad5118ff10090279cd0f9,00.html

The variations on this item in my config are below. I see that it works. I see that it has bugs (i.e., 17:10:00 fails). I'd like to understand what is happening. Some things I get, others I do not:

1) I do not understand where _d comes from in the example above. Does it matter?
2) I understand the typeset part; it assures the width of the hour/minute/seconds variables.
3) I do not understand why let is used in one place (let SECONDS), but not in the other (s=).
4) I do not understand the == in the SECONDS assignment.
5) Why are there no $ (dollar-signs) in the s variable assignment.
6) The [s] array reference totally blows my mind. What is this really?
7) I understand that a single-quote item will not be evaluated until run time.

One item at a time, please. I'm squinitng like I'm trying to straighten a corkscrew using only telekenses.

----- Begin script:

# Make certain that the length of time fields is 2-digit:
typeset -RZ2 hr min sec

# Get a string which is parsable to the number of seconds.
let SECONDS=$(/usr/bin/date '+3600*%H+60*%M+%S')

s='(hr=(SECONDS/3600)%24)==(min=(SECONDS/60)%60)==(sec=SECONDS%60)'
d=
TIME='"${d[s]}$hr:$min:$sec"'
export PS1=${TIME}':'

 

 

P.S. This thread has been moved from HP-UX > System Administration to HP-UX > languages - HP Forums Moderator

Command-Line Junkie
1 REPLY 1
David Totsch
Valued Contributor
Solution

Re: ksh time prompt PS1; It works, but *why*? (ksh obfuscation?)

I am suprised that all of the Olympians are not answering this one...could it be that they actually go home once in awhile, or are they taking National System Administrator appreciation day off...

${_d[_s]} is "slight-of-hand"...you have to trick the shell into making the evaluation set-up in that s='...' line. More about that later.

The 'let' makes sure the string returned by date(1) is evaluated to a number (sorta like eval would make a second pass on the same line), but let does arithmetic stuff.

ME=5+5

leaves ME containing the string "5+5"

let ME=5+5

leave ME containing the string "10".

Since the Bourne shell, we have gotten into the habit of evaluating arithmetic statements in other ways.

SECONDS is an automatic shell variable that contains the number of seconds since shell invocation. If you try to set SECONDS to a number, like the let in our example, SECONDS contains the number you set it to PLUS the number of seconds since shell invocation. Hence, SECONDS keeps the current time in seconds.

The output is "two" (stuff between square brackets is evaluated). And _s is a big, long, boolean equation that sets the variables "hr", "min", "sec" using the current value of SECONDS (yup, without the $). You can do the same with $((...)) or ((..)).

You could say that _d stands for "dummy" (we just needed a dummy array) and _s stands for "seconds string".

When the shell tries to print ${_d[_s]}, it evaluates _s arithmetically. Breaking down _s, hr=(SECONDS/3600)%24 is an arithmetic statement that sets hr to a number. It is also a boolean statement that is always true. Taking out the code that sets variables, you have

(...)==(...)==(...)

The '=='s are boolean statements testing for equality. They don't "do" anything but let one statement set all three variables.

To get a feel for how this works, consider the following code:

a[0]=zero
a[1]=one
a[2]=two
a[3]=three
a[4]=four

echo ${a[1+1]}


Hope that helps,
-dlt-