${VAR+T} True if VAR is set, even if it is empty
*Tags*: empty check, test empty
${VAR+T} True if VAR is set, even if it is empty
${VAR:+T} True if VAR is set and non-null
${VAR:-default_value} use the value of VAR if VAR is set and non-null, otherwise use "default_value"
${VAR:+value} return "value" if VAR is set and non-null, otherwise return VAR
In short, use the "check set" feature.
I have always want this feature. If a varible is defined, I want to use it, with a little bit of twisting. Else, if it is not defined, leave empty.
${ parameter :+ word }
If parameter is set and is non-null, substitute word; otherwise substitute nothing.
$ echo =$test_var= ==
$ echo =${test_var:-asdf}= =asdf=
$ echo =${test_var:+asdf}= ==
$ test_var=T
$ echo =${test_var:+asdf}= =asdf=
$ echo =${test_var:+pre-$test_var.post}= =pre-T.post=
no_log_url=F [ "x$1" = "x-n" ] && { no_log_url=T # don't log the url shift 1 }
[ $no_log_url = F ] && urllogging='-l'
gnuwget $urllogging -t "$file_title"...
Procmail borrows some sh syntax for variable initialisation. Note that available in a procmail rcfile.
VAR1 = ${VAR2:-value} sets VAR1 to VAR2 if VAR2 is set and non-null, and sets VAR1 to default "value" otherwise
VAR1 = ${VAR2-value} sets VAR1 to VAR2 if VAR2 is set, and sets VAR1 to default otherwise
VAR1 = ${VAR2:+value} sets VAR1 to "value" if VAR2 is set and non-null, and sets VAR1 to VAR2 otherwise.
VAR1 =${VAR2+value} Sets VAR1 to "value" if VAR2 is set and sets VAR1 to VAR2 otherwise.
And here are the classic usage examples
VAR = ${VAR:-"yes"} # set VAR to default value "yes" VAR = ${VAR+"yes"} # If VAR contains value, set "yes"
Ever wondered if this calls `date` in all cases?
VAR = ${VAR:-`date`}
No, procmail is smart enough to skip calling date if VAR already had value. It doesn't evaluate the whole line. Below you see what each initialising operator does. Study it carefully
VAR = "" # Define variable VAR = ${VAR:-"value1"} # VAR = "value1" VAR = "" VAR = ${VAR-"value2"} # VAR = ""
VAR = "" VAR = ${VAR:+"value3"} # VAR = "" VAR = "" VAR = ${VAR+"value4"} # VAR = "value4"
# Note these: VAR = "val" VAR = ${VAR:+"value3"} # VAR = "value3" VAR = "val" VAR = ${VAR+"value4"} # VAR = "value4"
VAR # kill the variable VAR = ${VAR:-"value1"} # VAR = "value1" VAR VAR = ${VAR-"value2"} # VAR = "value2"
VAR VAR = ${VAR:+"value3"} # nothing is assigned VAR VAR = ${VAR+"value4"} # nothing is assigned
$ DISP=``
— imitate an empty return
$ svs DISP DISP=
$ echo ${DISP:-'eee'} eee
— check null
$ echo ${DISP-'eee'}
— check set only
$ unset DISP
$ echo ${DISP-'eee'} eee
${parameter:-word} If parameter is set and is non-null, substitute its value; otherwise substitute word.
${parameter:=word} If parameter is not set or is null set it to word; the value of the parameter is substituted. Positional parameters may not be assigned in this way.
${parameter:?word} If parameter is set and is non-null, substitute its value; otherwise, print word and exit from the shell. If word is omitted, the message "parameter null or not set" is printed.
${parameter:+word} If parameter is set and is non-null, substitute word; otherwise substitute nothing.
If the colon (:) is omitted from the above expressions, the shell only checks whether parameter is set or not.
$ vtest=1234abcd $ ( echo $vtest ) 1234abcd
— sub-shells invoked from () take internal variables automatically, no need to export them first.
*Tags*: cmd:case
$ case $v in [cC]) echo found;; *) echo not found ;; esac
# all must be in current directory: case "$*" in */*) echo "nom quitting: I can't handle '/'s." >&2; exit ;; esac
case $1 in -[1-9]*) n=`expr 1 - "$1"` shift esac
xsel -p | perl -pe 's/[a-z]/[$&\u$&]/g'
$ echo '*.tar.gz | *.tgz' | perl -pe 's/[a-z]/\[$&\u$&\]/g' *.[tT][aA][rR].[gG][zZ] | *.[tT][gG][zZ]
$ v=c $ case $v in "c") echo found;; *) echo not found ;; esac found
$ v=C $ case $v in "c") echo found;; *) echo not found ;; esac not found
$ case $v in "[cC]") echo found | *) echo not found ;; esac not found |
$ case $v in [cC]) echo found | *) echo not found ;; esac found |
![]() |
!! |
![]() |
No quoting!: |
case "$src" in '/*') # referring to an abs point
will fail to operate while the following is ok:
case "$src" in /*) # referring to an abs point
documented on: 2000.08.15 Tue 16:55:16
Change from
eval $UNTGZ to
PROCESS=TGZ eval $UN$PROCESS
eval `echo \\$UN$PROCESS`
or,
eval `eval echo \\$UN$PROCESS`
PROCESS=TGZ UNTGZ=ls
$ eval `echo \$UN$PROCESS` -bash: TGZ: command not found
$ eval `echo \\$UN$PROCESS` 11getlog.lst cdt ...
UNTGZ='tar xzf $ZF' ZF=../test.org/bar.tar.gz
set -x
$ eval `echo \\$UN$PROCESS` ++ echo '$UNTGZ' + eval '$UNTGZ' ++ tar xzf '$ZF' tar (child): $ZF: Cannot open: No such file or directory
$ eval `eval echo \\$UN$PROCESS` ++ eval echo '$UNTGZ' +++ echo tar xzf '$ZF' + eval tar xzf '$ZF' ++ tar xzf ../test.org/bar.tar.gz
lvstr0='*[?&*]*' ... lvstr2='*['\''`~<>:#$?&* -]*' lvstr=\$lvstr2
$ lvstrn=`eval echo $lvstr` $ svf lvstr lvstr='$lvstr2' lvstr0='*[?&*]*' lvstr2='*['\''`~<>:#$?&* -]*' lvstrn='*['\''`~<>:#$?&* -]*'
a=123 b='The interpolated value for \$a is $a'
$ c=`eval echo $b`; svs c c=The interpolated value for $a is 123
These are no good:
$ c="$b"; svs c c=$a
$ eval c="$b" bash: want: command not found
$ v=PATH
$ echo \$"$v" $PATH
$ eval echo \$"$v" /export/home/tong/bin:/export/home/tong/local/bin:/usr/lib:/shared/local/bin:/usr/local/bin:/usr/shared/bin:/opt/gnu/bin:/bin:/shared/bin:/shared/sbin:/etc:/shared/ucb:/shared/ccs/bin:/shared/openwin/bin:/shared/dt/bin:/export/home/tong/bin/pf:/export/home/tong/bin/tcltk:.
b='The interpolated value for \$a$n is $a$n' c=`eval echo $b`; svs c
— c=The interpolated value for $a1 is 1
b=a a='ls -l'
$ echo \$"$b" $a $ eval \$"$b" total 256 -rw-r----- 1 tong tong 8262 Aug 17 17:09 Makefile [...]
— long list pwd
$ c=`eval echo "b de-refered to \\$b, which is " \\$"$b" `; svs c c=b de-refered to a, which is ls -l
These are no good:
$ c=`eval echo 'b de-refered to \\$b, which is \\$"$b"' `; svs c c=b de-refered to $b, which is $a
$ c=`eval echo 'b de-refered to \\$b, which is \\\\$"$b"' `; svs c c=b de-refered to $b, which is \a
$ c=`eval echo 'b de-refered to \\$b, which is \\\\\\$"$b"' `; svs c c=b de-refered to $b, which is \$a
>I'm trying hard to write a shell script to determine a compressed file >type. > >Ex. > >cft, stands for "compressed file type" > >cft xxx.tar.gz will give .gz >cft xxx.tar.Z will give .Z
But your example suggests the first most strongly to me, so:
for f; do echo ".${f##*.}"; done
is a near miss for ksh/bash (it doesn't correctly handle the case of no "." in the name). A more accurate version, which works for any Bourneish shell, is:
for f; do expr "$f" : '.*\(\..*\)'; done
>I know I can do it easily with perl but I hope a simple solution by sed >will do. Thanks for your help!
If you really want sed:
for f; do echo "$f" | sed 's/.*\././'; done
Ken Pizzini
> I'm wondering how would you test on the length of a string? Say to > test whether the variable $fname has the length longer than 2? > > I can use two (nested) expr command to do that or, one awk command > with echo: > > while `echo $fname | awk '{exit !(length() >2)}' `; do > > any other ways? thanks!
No external programs needed using ksh:
if [ ${#fname} -le 2 ] ; then print "shorter or equals 2" else print "longer than 2" fi
> How about bash? :-)
Normally for such simple examples ksh is quite close to bash syntax. It works if you do a s/print/printf/:
$ a=test $ if [ ${#a} -le 2 ]; then printf "shorter or equals 2"; else printf "longer than 2"; fi longer than 2
Best regards, Roberto Nibali, ratz
I only need one "expr" command:
if [ 0`expr "$fname" : '.*'` -gt 2 ] ...
The following part print the string length:
expr "$fname" : '.*'
Heiner
documented on: 2000.12.21 Thu 22:33:46
Newsgroups: comp.unix.shell
> > How can I get the first 4 character of a variable? > > MYVAR2=${MYVAR:0:4}
ksh variant:
typeset -L4 newvar=$MYVAR
Newsgroups: comp.unix.shell
> What's the best way to find out if a string has a certain letter in it? > So when i assign var=ABCD i would like to check if this var has a > letter B in it. How to do it ? (i can only think of a messy loop)
bourne shell :
case $var in *B*) echo found ;; *) echo not found ;; esac
korn shell (same as the bourne shell + ) :
if [[ $var = *B* ]]; then echo found else echo not found fi
Cyrille.
documented on: 2000.08.28 Mon 21:44:34
> tst1 a b "c d" > > tst2 $* <-- this would expand above to 4 args instead of 3. > tst2 "$*" <-- this would expand above to 1 arg instead of 3. > > How do I get the original three args?
tst2 "$@"
is equivalent to using
tst2 "$1" "$2" "$3"
In summary, for original example:
$@ 4 args $* 4 args "$*" 1 arg "$@" 3 args!
Beside, when there are no positional parameters, “$@” and $@ expand to nothing (i.e., they are removed). No need to play the trick ${1+"$@"}!
That "$@" string is sort of magical in the Bourne shell, it makes all the strings come out properly quoted. Not doubt there is some way to accomplish the same thing in csh/tcsh, but I don't know offhand how. Do yourself a favor and use tcsh as your interactive shell if you like, but program in sh/ksh.
documented on: 2000.06.21 Wed 16:30:54
>Q: How is ${3+"$3"} different than just writting $3 ?
If $3 in undefined, you get the same result. If $3 is defined, then the ${3+"$3"} version does not do word splitting or filename expansion on the contents of $3 --- so if $3 contains spaces or shell glob characters like * you will not be surprised. It is different from "$3" in that you do not wind up passing an empty string down to the command in the case that $3 is undefined.
documented on: 1999.09.13 Mon 14:07:39
> Fair enough, but the burning question is HOW?
Here are a few rudimentary examples which should get you started:
program |& # start program as co-process
read -p inputline # read line of data from co-process into variable # inputline
print -p "foo bar" # send data "foo bar" to co-process
anotherprogram <&p >&p # run another program, connecting its # standard input and standard output to co-process
exec 3<&p 4>&p # connect file descriptor 3 to input from co-process and # file descriptor 4 to output to co-process by default
read -u3 inputline # read data from co-process, this time through file # descriptor 3 (comparable syntax for print as well)
program2 |& # now that the prior co-process has been connected to file # descriptors, we can start a second co-process without # the two interfering with each other
Eric Amick