Расширение переменных Bash (возможно использование eval) в цикле for-do - PullRequest
0 голосов
/ 24 марта 2012

Я изучаю книгу "Начало программирования под Linux 4-е издание" , а глава 2 посвящена программированию оболочки.Я был впечатлен примером на странице 53 и попытался разработать сценарий, чтобы показать больше об этом.Вот мой код:

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 = + 

Как я могу получить желаемый результат?Когда я запускаю его как есть, я получаю только

PS1 = 
PS2 = 
PS3 = 
PS4 = +

Что случилось с PS1 и PS2?Почему я не получаю то же значение, которое получаю с

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

, потому что это то, что я пытаюсь получить.

Ответы [ 2 ]

1 голос
/ 24 марта 2012

Оболочка, выполняющая скрипт, всегда не является интерактивной оболочкой.Вы можете принудительно запустить скрипт в интерактивном режиме, используя параметр '-i':

Попробуйте изменить:

#!/bin/bash

на:

#!/bin/bash -i

см. Раздел ПРИЗНАНИЕв 'man bash' (bash.bashrc - это место, где определен ваш PS1):

       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.

вы также можете прочитать: http://tldp.org/LDP/abs/html/intandnonint.html

простой тест:

$ 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\] 
0 голосов
/ 24 марта 2012

Использовать косвенное расширение:

for j in 0 1 2 3 4; do
    psword="PS$j"
    echo "$psword = ${!psword}"
done
...