brant@manta.UUCP (Brant Cheikes) (03/08/88)
In a memo by David Korn describing ksh, there is a paragraph that states: "The ENV file can have an undesirable effect on performance. Even if this file is small, the shell must perform an open of this file. If large functions are placed in the ENV file they must be read in and compiled even if they are never referenced. If you only need the startup file for interactive shells, then set your ENV variable to a value which evaluates to a file name for interactive shells and to the null string otherwise. If you export the startup file name in the variable START, then setting ENV='${START[(_$-=1)+(_=0)-(_$-!=_{-%%*i*})]}' will only invoke the startup file for interactive shells since the subscript evaluates to 0 only if the shell is interactive." Now, I've done this and it works, but I can't quite figure out how. I've figured out the following: 1. $- evaluates to the shell args, for an interactive shell this is something like 'is', otherwise just 's'. 2. _$-=1 evaluates to _<shellargs>=1, e.g., _is=1 3. _=0 is just _=0 4. _$-!=_{-%%*i*} becomes _is!=_ (if shell args contains 'i') and _s!=_s otherwise. So for an interactive shell, we get (_is=1)+(_=0)-(_is!=_) At this point I'm lost. Don't the parenthesized items invoke subshells? How does this turn out to be 0? And how does it turn out to be 1 if the shell is non-interactive? Can anyone shed some light on how this little hack works? At least this little trick should be of general interest, since it's only documented in the internal ksh memo, not any of the manuals I've been able to find. -- Brant Cheikes University of Pennsylvania Department of Computer and Information Science ARPA: brant@linc.cis.upenn.edu, UUCP: ...drexel!manta!brant
marty1@houdi.UUCP (M.BRILLIANT) (03/12/88)
In article <340@manta.UUCP>, brant@manta.UUCP (Brant Cheikes) writes: > In a memo by David Korn describing ksh, there is a paragraph that > states: > > "The ENV file can have an undesirable effect on performance.... > .... If you export the startup file name in the > variable START, then setting > > ENV='${START[(_$-=1)+(_=0)-(_$-!=_{-%%*i*})]}' > > will only invoke the startup file for interactive shells since the > subscript evaluates to 0 only if the shell is interactive." > > Now, I've done this and it works, but I can't quite figure out how. I've figured out how, but I can't make it work. The manual entry for ksh says that the subscript in an array parameter, that is, x in $START[x], is evaluated as an arithmetic expression. In arithmetic evaluation, as described under the "let" command, you can put subexpressions in parentheses and use = for arithmetic replacement. In an interactive shell, $- usually evaluates to "is". So the first term in parentheses, (_$-=1), evaluates to 1 but also sets the identifier _is equal to 1. The second term, (_=0), evaluates to zero and sets the identifier _ to zero. The third term is apparently a misprint for (_$-!=_${-%%*i*}). The part before the != evaluates, as previously defined, to 1. The part after the != uses ${..%..} to lop off any trailing substring in $- that contains an i, so that part evaluates to _ (zero) in an interactive shell, but to _$- (=1) in a noninteractive shell. The != is true in an interactive shell, equals 1, but is false in an noninteractive shell, equals zero. The sum of the three terms is zero in an interactive shell but is 1 in a noninteractive shell. The desired effect is achieved if, as it says in the manual entry, "command and parameter substitution is performed on the value [of $ENV] to generate the pathname of the script ...." On my system, substitution doesn't seem to happen, so it doesn't work. M. B. Brilliant Marty AT&T-BL HO 3D-520 (201)-949-1858 Holmdel, NJ 07733 ihnp4!houdi!marty1 Disclaimer: Opinions stated herein are mine unless and until my employer explicitly claims them; then I lose all rights to them.
rupley@arizona.edu (John Rupley) (03/12/88)
In article <340@manta.UUCP>, brant@manta.UUCP (Brant Cheikes) writes: > >In a memo by David Korn describing ksh, there is a paragraph that > >states: > >If you export the startup file name in the variable START, then setting > > ENV='${START[(_$-=1)+(_=0)-(_$-!=_{-%%*i*})]}' > >will only invoke the startup file for interactive shells since the > >subscript evaluates to 0 only if the shell is interactive." > > Now, I've done this and it works, but I can't quite figure out how. > I've figured out the following: > 1. $- evaluates to the shell args, for an interactive shell this > is something like 'is', otherwise just 's'. > 2. _$-=1 evaluates to _<shellargs>=1, e.g., _is=1 > 3. _=0 is just _=0 > 4. _$-!=_{-%%*i*} becomes _is!=_ (if shell args contains 'i') and > _s!=_s otherwise. > So for an interactive shell, we get > (_is=1)+(_=0)-(_is!=_) > At this point I'm lost. Don't the parenthesized items invoke > subshells? How does this turn out to be 0? And how does it turn out > to be 1 if the shell is non-interactive? Awesomely neat trick! For Korn shell arithmetic, the parentheses establish high precedence. The assignments within them are just that, giving the value "1" to "_is" and "0" to "_". The value of the parenthesized expression is the assigned value. The two-fold cleverness is using the results of the first two assignments in the logical arithmetic test of the rightmost term, and then merging in the logical result (false=1 if "i" is set (1 != 0), true=0 if not) when evaluating the full expression. So the arithmetric expression evaluates: 1 + 0 - 1 if "i" is a shell parameter 1 + 0 - 0 if "i" is not a parameter Attached is a shell script that shows what happens, if you run ksh -x script for non-interactive shell ksh -i -x script for interactive shell > Brant Cheikes > University of Pennsylvania > Department of Computer and Information Science > ARPA: brant@linc.cis.upenn.edu, UUCP: ...drexel!manta!brant John Rupley uucp: ..{ihnp4 | hao!noao}!arizona!rupley!local internet: rupley!local@megaron.arizona.edu telex: 9103508679(JARJAR) (H) 30 Calle Belleza, Tucson AZ 85716 - (602) 325-4533 (O) Dept. Biochemistry, Univ. Arizona, Tucson AZ 85721 - (602) 621-3929 ---------------------------------------------------------------------- #script #run under ksh # ksh -x script # ksh -i -x script (( a1=(_$-=1) )) (( a2=(_=0) )) (( a3=(_$-!=_${-%%*i*}) )) (( a=(_$-=1)+(_=0)-(_$-!=_${-%%*i*}) )) b="${START[(_$-=1)+(_=0)-(_$-!=_${-%%*i*})]}" echo echo "INDEX= $a1 + $a2 - $a3 = $a and ENV=START[INDEX]=$b"
davek@heurikon.UUCP (Dave Klann) (03/22/88)
In article <1486@houdi.UUCP> marty1@houdi.UUCP (M.BRILLIANT) writes: [ Discussion about the startup variable, and how it works. ] >The desired effect is achieved if, as it says in the manual entry, >"command and parameter substitution is performed on the value [of $ENV] >to generate the pathname of the script ...." On my system, substitution >doesn't seem to happen, so it doesn't work. > >M. B. Brilliant Marty I fought this one for a while too. Then after playing with the script, and watching it carefully, I realized that the variable START (or its equivalent) must be exported for the hack to work. "DUH!," I said to myself. But hopefully this posting will help others avoid the same mistake.