Frage

I am studying the book "Beginning Linux Programming 4th ed" and chapter 2 is about shell programming. I was impressed by the example on page 53, and tried to develop a script to display more on that. Here is my code:

enter code here
#!/bin/bash
var1=10
var2=20
var3=30
var4=40
for i in 1 2 3 4 # This works as intended!
do
    x=var$i
    y=$(($x))
    echo $x = $y   # But we can avoid declaring extra parameters x and y, see next line
    printf "  %s \n" "var$i = $(($x))"
done
for j in 1 2 3 4  #This has problems!
do
    psword=PS$j
    #eval psval='$'PS$i   # Produces the  same output as the next line
    eval psval='$'$psword
    echo '$'$psword = $psval 
    #echo "\$$psword = $psval"    #The same as previous line
    #echo  $(eval '$'PS${i})   #Futile attempts
    #echo PS$i =  $(($PS${i}))
    #echo PS$i =  $(($PS{i}))
done

#I can not make it work as I want : the output I expect is
#PS1 = \[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$
#PS2 = >
#PS3 = 
#PS4 = + 

How can I get the intended output? When I run it as it is I only get

PS1 = 
PS2 = 
PS3 = 
PS4 = +

What happened with PS1 and PS2 ? Why do not I get the same value that I get with

echo $PS1
echo $PS2
echo $PS3
echo $PS4

because that was what I am trying to get.

War es hilfreich?

Lösung

Shell running a script is always non interactive shell. You may force to run the script in interactive mode using '-i' option:

Try to change:

#!/bin/bash

to:

#!/bin/bash -i

see INVOCATION section in 'man bash' (bash.bashrc is where your PS1 is defined):

       When an interactive shell  that  is  not  a  login  shell  is  started,  bash  reads  and  executes  commands  from
   /etc/bash.bashrc  and  ~/.bashrc,  if  these  files  exist.  This may be inhibited by using the --norc option.  The
   --rcfile file option will force bash to read and  execute  commands  from  file  instead  of  /etc/bash.bashrc  and
   ~/.bashrc.

   When  bash  is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in
   the environment, expands its value if it appears there, and uses the expanded value as the name of a file  to  read
   and execute.  Bash behaves as if the following command were executed:
          if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
   but the value of the PATH variable is not used to search for the file name.

you can also read: http://tldp.org/LDP/abs/html/intandnonint.html

simple test:

$ cat > test.sh
echo "PS1: $PS1"
$ ./test.sh 
PS1: 

$ cat > test.sh
#!/bin/bash -i            
echo "PS1: $PS1"
$ ./test.sh 
PS1: ${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] 

Andere Tipps

Use indirect expansion:

for j in 0 1 2 3 4; do
    psword="PS$j"
    echo "$psword = ${!psword}"
done
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top