#----------------------------------------------------------#

# ====> 红色字体 -特指煮酒个人所见。加粗则为需要重点注意。 #
# ====> 蓝色加粗 -特指与本文相关人员,包括参与修正的朋友。 #
# ====> 煮酒品茶 -Http://cwtea.blog.51cto.com          #
#----------------------------------------------------------#

 

 变量与算术

 
Posix Shell为内嵌(inline)算术提供了一种标记法,称为算术展开。Shell会对$((...))里的算术表达式进行计算,再将计算后的结果放回到命令的文本内容。
 
变量赋值为只读模式:
 
export,readonly
语法:
export name[=word]...
export -p
readonly name[=word]...
readonly -p
 
用途:export用于修改或打印环境变量,readonly则使得变量不得更改,
 
主要选面
-P:
打印命令的名称以及所有被导出(只读)变量的名称与值,这种方式可使得Shell重新读取输出以便重新建立环境(只读设置)
 
Posix标准允许你将赋值与命令的操作结合在一起。
 
unset命令从执行中的shell中删除变量与函数,默认情况下,它会解除变量设置,也可以加上-v来完成。
unset full_name 删除full_name变量
unset -v first middle last 删除其它变量
 
使用unset -f 删除函数:
who_is_on () {  定义函数
who |awk '{print $1}' |sort -u 产生排序后的用户列表
}unset -f who_is_on 册除函数
 
env
语法
env [-i] [var=value ...] [command_name] [arguments...]]
用途:当command_name被env执行时,可针对被command_name继承而来的环境有更细致的控制。
 
-i 忽略继承的环境,仅使用命令行上所给定的变量与值。
行为:未提供command_name时,显示环境中所有变量的名称与其值。否则,在命令行上使用变量赋值,在引用command_name之前,以修改继承的环境,加上-i选项,env会完全忽略继承的环境,县城只使用所提供的变量与值。
 
UNset
 
语法:
unset [-v ] variable ...
unset -f function ...
用途:从当前的Shell删除变量与函数
主要选项: -f 解除(删除)指定的函数
-v 解除(删除)指定的变量,在没有任何选项时,这是默认。
行为模式
如果没有提供选项,则参娄将视为变量名称,并告知变量已删除,使用-v选项也会发生相同的行为,如使用-f选项,参数则被视为函数名称,并删除函数。
 
参数展开:
a="hello 123"
sleep 120
echo $a
 
 
警告:
默认情况下,未定义的变量会展开为null字符品,程序随便乱写,就可能会导致灾难发生:
rm -rf /$myprogram 如果未设置myprogram那就完了。  测试是这样的
 
替换运算符:
${varname:=word} 如果varname存在且不是null,则返回它的值,否则,设置它为word,并返回其值。
用途:如果变量未定义,则设置变量为默认值。
 
${varname:?message}如果varname存在且非null,则返回它的值,否则,显示varname:message,并退出当前的命令或脚本。省略message会出现默认的信息parameeter null or not set。
 
${varname:+word} 如果varname存在且非null,则返回word,否则返回null。
用途:为测试变量的存在。
 
 
---------------
$a=""
${a:=hello}
echo $a
-------------------
$a的值为hello
 
 
模式匹配运算符
用法:
${variable#pattern} 如果模式匹配于变量值的开头处,则删除匹配的最短部分,并返回剩下的部分。
 
path =/home/tolstoy/mem/long.file.name
 
${path#/*/} >tolstoy/mem/long.file.name
${path##/*/} >long.file.name  如果模式匹配于变量值的开头处,则删除匹配的最长部分,并返回剩下的部分。
${path%.*} >/home/tolstoy/mem/long.file 如果模式匹配于变量值的结尾处,则删除匹配的最短部分,并返回剩下的部分。
${path%%.*} >/home/tolstoy/mem  如果模式匹配于变量值的结尾处,则删除匹配的最长部分,并返回剩下的部分。
 
一例:
--------------------------------------
[root@localhost test]# cat a
path=/home/tolstoy/mem/long.file.name
${path#/*/}
echo $path
[root@localhost test]# ./a
./a: line 2: tolstoy/mem/long.file.name: Permission denied  已经匹配,要替换则用上替换运算符。
/home/tolstoy/mem/long.file.name
[root@localhost test]# 
---------------------------------------
 
位置参数:
解释:SHell脚本的命令行参数,同时也表示在Shell函数内的函数参数。它们的名称是以单个整数来命令,出于历史原因,当这个整数大于9时,就应该以花括号({})括起来。
echo first arg is $1
echo tenth arg is ${10}
 
$# 供传递到Shell脚本或函数的参数总数。当你是为了处理选项和参数而立的循环时,它会很有用。
$*,$@ 一次表示所有的命令行参数,这两个参数可用来把命令行参数传递给脚本或函数所执行的程序。
"$*" 将所有命令行参数视为单个字符串,等同于“$1 $2...”$IFS的第一个字符用来作为分隔字符,以分隔不同的值来立字符串。
printf "The arguments were %s\n" "$*"
"$@" 将所有命令行参数视为单独的个体,也就是单独的字符串,等同于"$1" "$2"...这是将参数传递给其它程序的最佳方式,因为它会保留所有内嵌在每个参数里的任何空白。例:
lpr "$@" 显示每一个文件
set命令可以做的事很多,调用此命令而未给预任何选项,则它会设置位置参数的值,并将之前存的任何值丢弃。
 
解释:shift命令是用来截去来自列表的位置参数,由左开始,一旦执行shift,$1的初始值会永远消失,取而代之的是$2的旧值,$2的值,变成$3的旧值,以此类推,$#值则会依次减1,shift也可使用一个可选的参数,也就是要位移的参数的计数,单纯的Shift等同于shift 1。
 
------------------------------------
[root@localhost test]# cat a
set -- hello "hi there" greetings
#echo there are $# total arguments
 
echo 3*
for i in $*; 
do echo i is $i; 
done
 
echo 3@
for i in $@;
do echo i is $i;
done
 
echo I am "3@"
for i in "$@"
do echo i is $i
done
 
echo I am 3*
for i in "$*"
do echo I is $i
done
[root@localhost test]# ./a
3*
i is hello
i is hi
i is there
i is greetings
3@
i is hello
i is hi
i is there
i is greetings
I am 3@
i is hello
i is hi there
i is greetings
I am 3*
I is hello hi there greetings
[root@localhost test]# 
-----------------------------------
煮酒品茶:$@与$*都是单个拆开,而"$@"是不将""里的内容拆开,"$*"把所有的内容做一个整体,再将他们的值赋于变量。
 
特珠变量:
Shell还有很多额外的内置变量,有一些也具有单一字符,非文字或数字字母的名称,其他则是全由大写字母组成的名称。
------------------------------------------------------
#,目前进程的参数个数。
@,传递给当前进程的参数。置于双引号内,会展开为个别参数。
*,传递给当前进程的命令行参数,置于双括号内,展开时为一单独参数。
-,在引用时给的Shell 的选项。
?, 前一命令的退出状态。
$,shell的PID。
0,shell程序的名字。
!,最近一个后台命令的PID。可以此方式存储进程编号,然后通过wait命令同步。
HOME,主目录。
IFS,内部的字段分隔符,一般为制表符、空格、以及换行符。
LANG,当前locale的默认名称
LC_ALL,当前locale的名称。会覆盖LANG与其他LC_*变量。
LC_CTYPE,在模式匹配期间,用来确定字符类别的当前locale名称。
LINENO,刚执行过的行在脚本或函数内的行编号。
NLSPATH,在$LC_MESSAGES(XSI)所给定的信息语言里,信息目录的位置。
PATH,命令查找的路径。
PPID,父进程的进程编号。
PS1,主要的命令提示字符串,默认为“$”。
PS2,行继续提示字符串默认">"。
PS4,以set -x设置的执行跟踪的提示字符串,默认为“+”。
PWD,当前工作目录。
-----------------------------------------------------
 
 
算术运算符
---------------------------------------------
— +:对两个变量做加法。
— -:对两个变量做减法。
— *:对两个变量做乘法。
— /:对两个变量做除法。
— **:对两个变量做幂运算。
— %:取模运算,第一个变量除以第二个变量求余数。
— +=:加等于,在自身基础上加第二个变量。
— -=:减等于,在第一个变量的基础上减去第二个变量。
— *=:乘等于,在第一个变量的基础上乘以第二个变量。
— /=:除等于,在第一个变量的基础上除以第二个变量。
— %=:取模赋值,第一个变量对第二个变量取模运算,再赋值给第一个变量。
---------------------------------------------------------------
 
 
简便方法
-----------------------------
[root@localhost test]# cat ys
set -x
i=5
echo $((i++)) $i
echo $((++i)) $i
[root@localhost test]# ./ys
++ i=5
++ echo 5 6
5 6
++ echo 7 7
7 7
[root@localhost test]# 
-----------------------------
 
退出状态:
解释:每条命令,不管是内的shell函数还是外部的,当它退出时,都会返回一个小的整数值给引用它的程序,即为退出状态。
0表示成功。
 
shell退出状态
------------------------
[root@localhost test]# echo $?
0
[root@localhost test]# lss foo
-bash: lss: command not found
[root@localhost test]# echo $?
127
---------------------------
0 成功退出
>0 在重定向或单词展开期间(~,变量,命令、算术展开,以及单词切割)失败。
1-125 命令不成功地退出,
126 命令找到了,但文件无法执行
127 命令找不到
>128 命令因收到信号而死亡
------------------------------
 
exit
语法:exit [exit-value]
用途:目的是从Shell脚本返回一个退出状态给脚本的调用者。
行为模式:如果没有提供,则以最后一个执行命令的退出状态作为默认的退出状态,如果这就是你要的,则最好明白地在shell脚本里这么写 exit $?
 
if-elif-else-fi
语法:
----------------------------
if pipeline
[pipeline...]
then
statements-if-true-1
[elif pipeline]
[pipeline...
then
statements-if-true-2 ...]
[else
statements-if-all-else-fails ]
fi
-------------------------
(方括号内表示可选部分)
 
test
解释:test命令可以处理shell脚本里的各烊工作,它产生的不是一般输出,而是可使用的退出状态。test接受各种不同的参数,它控制它要执行的哪一种测试。
test命令有另一种形式:[...],这各用法的作用完全与test命令一样。
if test "$str1"= "str2" 与if ["$star1"="str2"]一样。
 
test,[...]
语法:test [ expression ]
[ [ expression ] ]
用途。为了测试shell脚本里的条件,通过退出状态返回其结果,要特别注意的是:这个命令的第二种形式,方括号根据字面意义靛字的输入,且必须与括起来的expression以空白隔开。
 
在XSI兼容的系统里,它的表达式可以与-a(逻辑的AND)与-o(逻辑的OR)结合使用。
优先级:
-a>-o>其它二无运算符
 
 

 
注: if [ -f "$file" ]  必须加引号
if [ "X$answer" = "Xyes" ] ... 新时代的用法。
-----------------------------
[root@localhost test]# cat test
set -x
file=~/test/a
if [ -f "$file" ] &&  [ -w "$file" ]
 
then
echo $0: $file is not writable, giving up. >&2
else
echo no
exit 1
fi
[root@localhost test]# ./test
++ file=/root/test/a
++ '[' -f /root/test/a ']'
++ '[' -w /root/test/a ']'
++ echo ./test: /root/test/a is not writable, giving up.
./test: /root/test/a is not writable, giving up.
----------------------------------------
 
case语句
 
添加服务里面还不错。
----------------------
case $1 in
-f)
...
;;
-a) | grep 允许长选项,这里|字符指或
...
;;
*)
esac
-------------------------------
要测试的值出现在case与in之间,发现匹配的时候,便执行相对应的程序代码,直至;;为止。可以使用多个模式,只要用|字符加以分隔时可,模式里会包含任何的shell通配字符,且变量,命令与算术替换会在它用作模式匹配之前在此值上被执行。
 
循环:
for循环:
--------------
for i
do
case $i in
-f) ...
;;
...
esac
done
------------------
while与until循环:
while/until conditon
do 
statements
done
 
不同之处:对待condition的退出状态,只要condition是成功退出,while会继续循环,只要condition未成功结束,until则执行循环。until在等待某个事件发生,它就很有作用。
 
break与continue
 
什么命令都不必做,只是成功地巡视出,用于编写无限循环。即会永久执行的循环。
 
continue用于提早开始下一段重复的循环操作,也就是在到达循环体的底部之前。
break与continue命令都接受可选的数值参数,可分别用来指出要中断(break)或继续多少个被包含的循环。
 
shift与选项的处理
shift:用来处理命令行参数的时候,一次向左位移一位(或更多位),默认为1
 
getopts:
语法:getopts option_spec variable [ arguments ... ]
用途:简化参数处理,并且让shell脚本可以轻松地匹配于posix参数处理惯例。
 
函数:
解释:是指一段单独的程序代码,用以执行一些定义完整的单项工作。
注意:在shell函数体里使用exit,会终止整个shell脚本。
 
return
语法: return [ exit-value ]
用途:返回由shell函数得到的退出值给调用它的脚本。
 
 
总结:特珠变量、运算符、if for while until test return getopts shift $.