shell之变量与read

时间:2023-12-14 15:05:38

环境变量  set  环境变量可供shell以外的程序使用

shell变量  env  shell变量仅供shell内部使用

set:显示(设置)shell变量 包括的私有变量以及用户变量,不同类的shell有不同的私有变量 bash,ksh,csh每中shell私有变量都不一样。
env:显示(设置)用户变量。
export:显示(设置)当前导出成用户变量的shell变量。
总结:linux 分 shell变量(set),用户变量(env),shell变量包含用户变量,export是一种命令工具,是显示那些通过export命令把shell变量中包含的用户变量导入给用户变量的那些变量.
使用unset命令来清除环境变量,注意set env export设置的变量,都可以用unset来清除的

目录栈的变量 DIRSTACK

控制提示符的变量 PROMPT_COMMAND

15:59:36 39 ~:#echo $PROMPT_COMMAND
printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"
16:01:20 40 ~:#PROMPT_COMMAND="date +%H%M"
16:03:11 44 ~:#uptime
 16:03:16 up 7 days,  7:02,  1 user,  load average: 0.00, 0.00, 0.00

16:04:00 49 ~:#date
Mon May 18 16:16:11 CST 2015

变量赋值

变量的赋值有五种:使用read命令,直接赋值,使用命令行参数,使用命令行的输出结果,从文件读取。
1 先说一下从read命令吧:(主要是在需要交互时使用)
Read命令是系统内置命令,语法格式为:
read 变量1 变量2
当Shell脚本执行到read命令时,将暂停脚本的执行并等待键盘的输入,当用户输入完毕并且敲下回车之后,将完成赋值操作,脚本继续执行。
Read指令的规则:
多个数据或变量之间用空格隔开
若变量个数与数据个数相等时,对应取值
若变量个数大于数据个数时,没有输入数据的变量取空值
若变量个数小于数据个数时,将多余的数据赋给最后一个变量(也就是把空格当成字符串处理)

例子:
#!/bin/bash
echo -n “ please enter your name” //-n 表示用户输入和提示信息在同一行
read name
echo “your name is $name”
#!/bin/bash
echo “Please enter your first name and last name :”
read first last
echo “your first name is $first”
echo “your last name is $last”

2 第二种赋值方法就是直接给变量赋值(这种赋值方法主要是在不需要交互时,并且参数不需要修改时使用)
例如:name=xiaosu
gender=man
3 第三种赋值方法是使用命令行参数赋值。(这种赋值方法是参数需要经常变化,并且不需要交互时使用)
这种赋值方法,也就是直接在命令后面跟参数,然后系统用$1来引用第一个参数。
a="$PWD"
echo $a

filename=$1
if [ -e "${filename}" ]

[root@-shiyan sh]# cat >myls
a=$
if [ -f $a ]
then
echo "$a is file"
else echo "unknown"
fi
[root@-shiyan sh]# ./myls fr
fr is file
[root@-shiyan sh]# ./myls awk
unknown [root@-shiyan sh]# cat >myls
while read $
do
echo "$1"
shift
done
###一直循环,除非按ctrl+c才能退出。
[root@-shiyan sh]# ./myls fr for his fr for his

4 第四种方法是利用命令的输出结果赋值(这种赋值方法可以直接处理上个命令产生的数据)
在Shell程序中,可以将一个命令的输出结果来当做变量,不过需要在赋值语句中使用反引号
例如currentdir=`pwd`
echo $currentdir
5 最后一种赋值方法是从文件中读入数据
这种方式就适合处理大批量的数据,直接把相应的数据写入文件,然后运行脚本即可。
通常是通过while循环一行行读入数据,即每循环一次,就从文件中读取一行数据,直到读取到文件的结尾。
例如:
#!/bin/bash
ls *.sh >execfile
while read LINE
do
chmod a+x $LINE
done <execfile
这个脚本使用了while..do..done 结构,最后一行表示从文件execfile读取数据。while read LINE表示 每次循环读入一行数据并赋值给变量LINE。

6 变量的输出
最简单的方法就是使用echo
如果想输出格式化的字符串,就需要使用printf,用法和C语言类似
printf 命令的格式说明符
\” 输出双引号
\\ 输出反斜杠
\a 响铃
\n 换行
\r 回车

位置参数

$1直到$N,大于10,要用${10}表示。

特殊参数

$! $@ $# $$ $* $? $0 $- $_

# vi variable
#!/bin/sh
echo "number:$#"
echo "scname:$0"
echo "first:$1"
echo "second:$2"
echo "argume:$@"
echo "show parm list:$*"
echo "show process id:$$"
echo "show precomm stat:$?"
# chmod +x variable
# ./variable aa bb
number:2
scname:./variable
first:aa
second:bb
argume:aa bb
show parm list:aa bb
show process id:24544
show precomm stat:0
通过显示结果可以看到:
$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
该变量包含了所有输入的命令行参数值。如果您运行showrpm openssh.rpm w3m.rpm webgrep.rpm
此时 $* 包含了 3 个字符串,即openssh.rpm, w3m.rpm and webgrep.rpm.

$* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。
但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

$!  显示最近运行的后台进程ID
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误

$- 记录着当前设置的shell选项,himBH是默认值,你可以通过 set 命令来设置或者取消一个选项配置。

[root@host02 rc0.d]# echo $-
himBHP

[root@250-shiyan /]# cd
[root@250-shiyan ~]# echo $_
cd
[root@250-shiyan ~]# ls
anaconda-ks.cfg  c  cccc  chpa1.sh  install.log  install.log.syslog  sh
[root@250-shiyan ~]# echo $_
--color=auto

[root@-shiyan sh]# cat vari1
#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"
echo "\$@=" $@
echo "\"\$@\"=" "$@"
echo "print each param from \$*"
for var in $*
do
echo "$var"
done
echo "print each param from \$@"
for var in $@
do
echo "$var"
done
echo "print each param from \"\$*\""
for var in "$*"
do
echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
echo "$var"
done
[root@-shiyan sh]# ./vari1 ei ei fefo fefw
$*= ei ei fefo fefw
"$*"= ei ei fefo fefw
$@= ei ei fefo fefw
"$@"= ei ei fefo fefw
print each param from $*
ei
ei
fefo
fefw
print each param from $@
ei
ei
fefo
fefw
print each param from "$*"
ei ei fefo fefw
print each param from "$@"
ei
ei
fefo
fefw
[root@-shiyan sh]#

bash-read

在read命令行中也可以不指定变量.如果不指定变量,那么read命令会将接收到的数据放置在环境变量REPLY中。
环境变量REPLY中包含输入的所有数据,可以像使用其他变量一样在shell脚本中使用环境变量REPLY.
[root@localhost ~]# read
fjdksfief
[root@localhost ~]# echo $REPLY
fjdksfief
[root@localhost ~]# read
SKFIEFJEIFFEIWOEFJ
[root@localhost ~]# echo $REPLY
SKFIEFJEIFFEIWOEFJ 计时输入.
使用read命令存在着潜在危险。脚本很可能会停下来一直等待用户的输入。如果无论是否输入数据脚本都必须继续执行,那么可以使用-t选项指定一个计时器。
-t选项指定read命令等待输入的秒数。当计时满时,read命令返回一个非零退出状态;
#!/bin/bash
if read -t 5 -p "please enter your name:" name
then
    echo "hello $name ,welcome to my script"
else
    echo "sorry,too slow"
fi
exit 0
除了输入时间计时,还可以设置read命令计数输入的字符。当输入的字符数目达到预定数目时,自动退出,并将输入的数据赋值给变量。
#!/bin/bash
read -n1 -p "Do you want to continue [Y/N]?" answer
case $answer in
Y | y)
      echo "fine ,continue";;
N | n)
      echo "ok,good bye";;
*)
     echo "error choice";;
esac
exit 0
该例子使用了-n选项,后接数值1,指示read命令只要接受到一个字符就退出。只要按下一个字符进行回答,read命令立即接受输入并将其传给变量。无需按回车键。 -p选项,就可以不用echo了
[root@localhost ~]# read -p "please input:" a;if [ $a -eq ]; then echo ; else echo ; fi
please input: [root@localhost ~]# read -p "please input:" a;if [ $a -eq ]; then echo ; else echo ; fi
please input: [root@localhost ~]# read -p "please input:" a;if [ $a -eq ]; then echo ; else echo ; fi
please input: [root@localhost ~]# read -p "please input:" a;if [ $a -eq ]; then echo ; else echo ; fi
please input:d
-bash: [: d: integer expression expected -s选项不显示输入
默读(输入不显示在监视器上)
有时会需要脚本用户输入,但不希望输入的数据显示在监视器上。典型的例子就是输入密码,当然还有很多其他需要隐藏的数据。
-s选项能够使read命令中输入的数据不显示在监视器上(实际上,数据是显示的,只是 read命令将文本颜色设置成与背景相同的颜色)。
[root@localhost ~]# read -s  a;if [ $a -eq 1 ]; then echo 2; else echo 4; fi
4
[root@localhost ~]# read -s  a;if [ $a -eq 1 ]; then echo 2; else echo 4; fi
2 还可以使用read命令读取Linux系统上的文件。
每次调用read命令都会读取文件中的"一行"文本。当文件没有可读的行时,read命令将以非零状态退出。
读取文件的关键是如何将文本中的数据传送给read命令。
最常用的方法是对文件使用cat命令并通过管道将结果直接传送给包含read命令的 while命令
cat 命令的输出作为read命令的输入,read读到的值放在line中
[root@localhost ~]# cat test
qqqq
www
eee
e
e
e
rrrtt
[root@localhost ~]# cat 123
#!/bin/bash
count=1
cat test | while read line
do
   echo "Line $count:$line"
   count=$[ $count + 1 ]
done
echo "finish"
[root@localhost ~]# source 123
Line 1:qqqq
Line 2:www
Line 3:eee
Line 4:e
Line 5:e
Line 6:e
Line 7:rrrtt
finish