您的位置:首页 > 运维架构 > Shell

shell程序设计笔记

2014-08-02 11:07 274 查看
1 shell是什么

shell是一个作为用户与Linux系统间接口的程序,它允许用户向操作系统输入需要执行的命令。

2 shell的种类

UNIX系统常见的shell
名称
路径
相关历史
Bourne shell
/bin/sh
源于UNIX早期版本的最初shell
Bourne-again shell

/bin/bash

GNU shell,所有Linux系统都提供。遵循POSIX且与Bourne shell兼容,可免费获取其源代码。
C shell

/bin/csh

由Bill Joy在Berkeley UNIX上开发,所有BSD版本都提供这种shell。其控制流类似于C语言。
Korn shell

/bin/ksh

由David Korn在贝尔实验室开发,是Bourne shell的后继者。
3 shell同类技术及优缺点对比

可参考博客:对python与shell的一些思考

4 shell语法

4.1 shell脚本运行

1> 交互式程序

交互式即是在命令行上直接输入shell脚本。

<span style="font-size:14px;">$ for file in *
> do
> if grep -l bin $file
> then
> more $file
> fi
> done
1.sh
</span>


当shell期待进一步的输入时,正常的$提示符将改变为>提示符。你可以一直输入下去,由shell来判断何时输入完毕并立刻执行脚本程序。
2> 创建脚本

编辑包含命令的脚本文件first.sh

<span style="font-size:14px;">#!/bin/sh

#this file is first.sh

for file in *
do
if grep –l bin $file
then
echo $file
fi
done
exit 0
</span>


程序中的注释以#开始,一直持续到该行的结束。
第一行#!/bin/sh的#!是一种特殊形式的注释,其告诉系统同一行上紧跟其后面的参数是用来执行本文件的程序。
编辑

Linux环境下可用vi或vim等编辑器。

Windows环境下可用notepad++、gvim等编辑器,当mount到linux虚拟机上运行时,需要转换下脚本的文件格式,

使用命令:dos2unix filename

运行

<span style="font-size:14px;">$ /bin/sh filename

或

$ chmod 755 filename

$ ./filename
</span>


3> 后台模式运行脚本

当脚本在运行时,你没法在终端会话里做别的事情。而利用ps命令查看,有一系列不同进程运行在linux上。显然这些进程都不是运行在你的终端上的。这些进程我们称为后台运行进程。在后台模式中,进程运行时不会和终端会话上的STDIN、STDOUT以及STDERR关联。要让脚本在命令行界面以后台模式运行,只要在命令后加个&符就行。如:

$ ./1.sh &

4.2 变量

shell的变量类型主要分为三种:1>用户变量2>环境变量3>特殊变量

4.2.1 用户变量

Shell脚本允许用户根据需要在脚本中定义和使用自己的变量。

命名
变量名由不超过20个字母、数字或下划线组成,不以数字开头且区分大小写
赋值
直接赋值格式:变量名=值(注:变量名等号和值之间不能出现空格)

交互赋值格式:read变量名(注:变量在使用之前不需要事先声明)
取值
$变量名
作用域
仅限于当前shell脚本中使用,其他的shell脚本不能使用
生命周期
在当前shell脚本的整个生命周期里一直存在,直到shell脚本完成时删除掉
.局部变量

要让一个变量成为某函数里的局部变量,只需在变量前加关键字local即可。如此,局部变量仅在函数的作用范围内有效。

例如: foo() {local var=123 …}函数中var为局部变量。

.只读变量

要让一个变量成为只读变量,只需要在变量前加上关键字readonly即可。只读变量一旦定义就不可更改其值,也不能用unset删除。

例如:readonly var=123 或

var=123

readonly var

.数组变量

定义数组

格式:array_name=(value0value1 value2 value3 …)或者

array_name=(

value0

value1

value2



)

或者
array_name[0]=value0

array_name[1]=value1

array_name[2]=value2

……
注意:各元素之间用空格隔开,数组下标从0开始。

数组取值
${array_name[index]}
获取下标为index的数组值
${array_name[*]}
获取整个数组的值
${#array_name[*]}
获取数组元素个数
${array_name[@]}
获取整个数组的值,可以处理包含空格的数组元素
数组部分取值 array_name=(10 11 12 13 14 15}
${array_name[*]:0}
结果为所有元素:10 11 12 13 14 15
${array_name[*]:1}
结果为第一个元素除外,其他所有元素:11 12 13 14 15
${array_name[*]:0:2}
结果为:10 11
${array_name[*]:0:4}
结果为:10 11 12 13
${array_name[*]:1:2}
结果为:11 12
${array_name[*]:1:4}
结果为:11 12 13 14
${array_name[*]:2:4}
结果为:12 13 14
子串删除 array_name=([0]=one [1]=two [2]=three [3]=four}
${array_name[*]#t*e}
左边开始最短的匹配:”t*e”。结果匹配到thre
${array_name[*]##t*e}
左边开始最长的匹配:”t*e”。结果匹配到three
${array_name[*]%o}
从字符串的结尾开始最短匹配:o。结果[1]为tw
${array_name[*]%%o}
从字符串的结尾开始最长匹配:o。结果为[1]为tw
子串替换 array_name=([0]=one [1]=two [2]=three [3]=four}
${array_name[*] /o/m}
第一个匹配到字符o的会被替换为字符m
${array_name[*] //o/m}
所有匹配到字符o的都会被替换为字符m
${array_name[*] //o/}
没有指明替换字符串,则删除匹配到的字符o
${array_name[*] /#o/k}
替换字符串前端子串。结果:kne two three four
${array_name[*] /%o/k}
替换字符串后端子串。结果:one twk three four
删除数组
unset array_name[1]
删除数组中的第一个元素
unset array_name
删除整个数组
.导出变量

通过export命令,可将作为它参数的变量导出到子shell中,并使之在子shell中有效。

4.2.2 环境变量

Linux是一个多用户的操作系统。多用户意味着每个用户登录系统后,都有自己专用的运行环境。而这个环境是由一组变量所定义,这组变量被称为环境变量。用户可以对自己的环境变量进行修改以达到对环境的要求。

Shell用环境变量来获取系统信息、存储有关shell会话和工作环境的信息和配置信息。环境变量也可用来存储永久数据,这些数据可以是用来识别用户账户、系统、shell的特性以及任何其他需要存储的数据。

Bash shell中,环境变量分为两类:1全局变量 2局部变量

全局环境变量不仅对shell会话可见,对所有shell创建的子进程也可见。可使用env命令查看。

局部环境变量则只对创建它们的shell可见。可使用set命令查看。

<span style="font-size:14px;">查看全局环境变量的命令:printenv
$ printenv
TERM=vt100
SHELL=/bin/bash
XDG_SESSION_COOKIE=4e89c702f201d9551a9ed9a653f35a9a-1409769542.760812-1100647347
SSH_CLIENT=192.168.0.100 16257 22
SSH_TTY=/dev/pts/1
USER=lincoln
LS_COLORS=rs=….
MAIL=/var/mail/lincoln
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
PWD=/home/lincoln
LANG=en_US.UTF-8
SPEECHD_PORT=7560
SHLVL=1
HOME=/home/lincoln
LANGUAGE=en_US:en
LOGNAME=lincoln
SSH_CONNECTION=192.168.0.100 16257 192.168.0.106 22
LESSOPEN=| /usr/bin/lesspipe %s
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/printenv
</span>


常见环境变量
环境变量
说明
HOME
当前用户的主目录
PATH
以冒号分隔的用来搜索命令的目录列表
HISTSIZE
历史记录数
LOGNAME
当前用户的登录名
HOSTNAME
主机的名称
SHELL
当前用户shell类型
LANGUGE
语言相关的环境变量
MAIL
当前用户的邮件存放目录
IFS
输入域分隔符。当shell读取输入时,它给出用来分隔单词的一组字符,它们通常是空格、制表符和换行符
PS1
命令提示符。root用户是#,普通用户是$
PS2
二级提示符。默认是>字符
4.2.3 特殊变量

Shell特殊内置变量通常也被称为参数变量,主要被shell脚本用来从命令行接收参数、或者被函数用来保存传给它的参数。

参数变量
说明
$0
Shell脚本的名字
$#
传递给脚本的参数个数
$$
Shell脚本的进程号,通常用它来生成一个唯一的临时文件,如/tmp/tmpfile_$$
$1, $2, …
Shell脚本的参数,第1个参数、第2个参数、…
$*
在一个变量中列出所有的参数,各个参数之间用环境变量IFS中的第一个字符分隔开。
$@
除了被双引号引用的情况,含义与$*相同,且不使用IFS环境变量
"$*"
其值为"$1 $2 $3"
"$@"
其值为"$1" "$2" "$3"
$-
当前的sh选项设置
$?
已执行的上一条命令的退出值
$!
最后一个进入后台的作业的PID
4.2.4 管道重定向引号反引号及其他

重定向输出
ps > psoutput.txt
将标准输出重定向到文件psoutput.txt。默认情况下,如果该文件已经存在,其内容将被覆盖。

命令:set –o noclobber设置noclobber选项,改变默认行为,从而阻止重定向操作对一个已有文件的覆盖。

命令:set +o noclobber取消该选项。
ps >> psoutput.txt
将标准输出内容附加到一个文件的尾部
Kill –HUP 1234 2>killerr.txt
将标准错误重定向到killerr.txt文件。文件描述符加在>操作符前面,可重定向其对应的文件
Kill –l 1234 >killouterr.txt 2>&1
将标准输出重定向到文件killouterr.txt,然后将标准错误输出重定向到与标准输出相同的地方。
重定向输入
more < killout.txt
将killout.txt文件重定向标准输入
管道操作符|
ps | sort > pssort.out
等价于:

ps > psout.txt

sort psout.txt > pssort.out
引号
myvar="Hi there"
如果想在一个参数中包含一个或多个空白字符,须给参数加上引号
echo "$myvar"
$变量表达式放在双引号中,变量会被替换为它的值。结果:Hi there
echo '$myvar'
$变量表达式放在单引号中,变量不会发生替换。结果:$myvar
echo \$myvar
\字符取消$的特殊含义。结果:$myvar
反引号
test=`date`
反引号允许将shell命令的输出赋值给变量
4.3 条件语句

if语句(条件为真值为0,条件为假值为1)
if test …

then



fi
if [ … ];then


fi
if test …

then



else



fi
if [ … ]

then



else



fi
if test …

then



elif test …

then



else



fi
if [ … ]

then



elif [ … ]

then



else



fi
case语句
case variable in

pattern [ | pattern] …) statements;;

pattern [ | pattern] …) statements;;



esac
test命令可以使用的条件类型可以归为3类:1>字符串比较2>算术比较3>文件有关的条件测试

字符串比较
结果
string1 = string2 或 str1 == str2
如果两个字符串相同则结果为真(值为0)
string1 != string2
如果两个字符串不同则结果为真
-n string
如果字符串不为空则结果为真
-z string
如果字符串为空则结果为真
算术比较
结果
expression1 –eq expression2
如果两个表达式相等则结果为真
expression1 –ne expression2
如果两个表达式不相等则结果为真
expression1 –gt expression2
如果expression1大于expression2则结果为真
expression1 –ge expression2
如果expression1大于等于expression2则结果为真
expression1 –lt expression2
如果expression1小于expression2则结果为真
expression1 –le expression2
如果expression1小于等于expression2则结果为真
!expression
如果表达式为假则结果为真,反之亦然
文件条件测试
结果
-d file
如果文件是一个目录则结果为真
-f file
如果文件是一个普通文件则结果为真
-g file
如果文件的set-group-id位被设置则结果为真
-u file
如果文件的set-user-id位被设置则结果为真
-s file
-e file
如果文件的大小不为0则结果为真
如果文件存在则结果为真
-r file
如果文件可读则结果为真
-w file
如果文件可写则结果为真
-x file
如果文件可执行则结果为真
复合条件

方式1:

与:

if [ 条件1 ] && [ 条件2 ] && [ 条件3 ]; then ... fi

说明:先判断条件1是否为真,当条件1不为真时,直接退出;当条件1为真时,再去判断条件2是否为真。

或:

if [ 条件1 ] || [ 条件2 ] || [ 条件3 ]; then ... fi

非:

if [ ! 条件 ]; then ... fi

方式2:

与: if [ 条件1 -a 条件2 ]; then ... fi

说明:同时判断条件1和条件2是否为真。

或: if [ 条件1 -o 条件2 ]; then ... fi

非: if [ !条件 ]; then ... fi

4.4 循环语句

for循环语句
for variable in values

do

statements

done
循环处理一组值。这组值可以是任意字符串的集合。for in 把values字符串按照空格划分。
while循环语句
while test command
do

statements

done
只有测试条件成立,while命令才会继续遍历执行。适合重复执行一个命令序列,但又不知道执行次数的情况
until循环语句
until tesst command

do

statements

done
与while命令工作方式完全相反。只有测试命令的退出状态码非零,until命令才会继续执行。
名称
说明
语法
合并匹配模式
|
var1 | var2 | var3 | …
AND列表
&&
statement1 && statement2 && …
OR列表
||
statement1 || statement2 || …
语句块
{}
{

statement1



}
示例:grep -E "2010-01-01|hello" filename #在文件filename中搜索2010-01-01和hello的行

4.5 命令

Shell程序内部可执行两类命令:
<1>外部命令,即可以在命令提示符中执行的普通命令。
<2>内部命令,即在shell内部实现的内置命令。
4.5.1 break命令

break命令在控制条件未满足之前,跳出for、while或until循环。默认情况下,break只跳出一层循环。也可为break提供数值参数来表明需要跳出的循环层数,但不建议这么做。

4.5.2 continue命令

continue命令使for、while或until循环跳到下一次循环继续执行,循环变量取循环列表中的下一个值。也可为continue提供数值参数来表明需要跳过几次循环。

4.5.3 :命令

冒号(:)命令是一个空命令。

作用1>简化条件逻辑。

<span style="font-size:14px;">if [ -f fred ];
then
:
else
echo file fred did not exist
fi
</span>

作用2>true的别名

while : 实现了一个无限循环,代替更常见的while true。

作用3>:${var:=value} #说明:当var为未赋值或为空时,将value的值赋给var。若没有前面的冒号:,则${var:=value}会报错。

4.5.4 .命令

通常,当一个脚本执行一条外部命令或脚本程序时,它会创建一个新的环境(一个子shell),命令将在这个心环境中执行,在命令执行完毕后,这个环境被丢弃,留下退出码返回给父shell。
外部的source命令和点(.)命令在执行脚本程序中列出的命令时,使用的是调用该脚本程序的同一个shell。
4.5.5 echo命令

echo命令用来输出结尾带有换行符的字符串。

echo hello world
结果:hello world
echo "you're lincoln?"
结果:you're lincoln?
echo 'do you know "lincoln"'
结果:do you know "llincoln"
去掉换行符的方法:

1>echo –n “stringto output”

2>printf “stringto output”

4.5.6 eval命令

eval命令用来对参数进行求值。

<span style="font-size:14px;">foo=10
x=foo
y='$'$x
echo $y
结果输出foo
foo=10
x=foo
eval y='$'$x
echo $y
结果输出:10
</span>


4.5.7 exec命令

exec的典型用法是将当前shell替换为一个不同的程序。
exec wall "Thanksfor all the fish"
该命令会用wall命令替换当前的shell。脚本程序中exec命令后面的代码都不会执行,因为执行这个脚本的shell已经不存在。
4.5.8 exit n命令

exit命令使脚本程序以退出码n结束运行。
如果脚本程序在退出时不指定一个退出状态,那该脚本中最后一条被执行命令的状态将被用作为返回值。
4.5.9 export命令

export将作为它参数的变量导出到子shell中,并使之在子shell中有效。
在默认情况下,在一个shell中被创建的变量在这个shell调用的子shell中是不可用的。export命令把自己的参数创建为一个环境变量,而这个环境变量可以被当前程序调用的其他脚本和程序看见。

<span style="font-size:14px;">#!/bin/sh
#this file is export2.sh
echo “$foo”
echo “$bar”
</span>
<span style="font-size:14px;">#!/bin/sh
#this file is export1.sh
foo=”The first meta-syntactic variable”
export bar=”The second meta-syntactic variable”
export2.sh</span>

$ export1.sh

4.5.10 expr命令

expr命令将它的参数当作一个表达式来求值。
x=$(expr $x+1)
expr命令可以完成许多表达式求值计算。
表达式求值
说明
expr1 | expr2
expr1 & expr2
expr1 = expr2
expr1 > expr2
expr1 >= expr2
expr1 < expr2
expr1 <= expr2
expr1 != expr2
expr1 + expr2
expr1 – expr2
expr1 * expr2
expr1 / expr2
expr1 % expr2
如果expr1非零,则等于expr1,否则等于expr2
只要有一个表达式为零,则等于零,否则等于expr1
等于
大于
大于等于
小于
小于等于
不等于
加法
减法
乘法
除法
取余
4.5.11 printf命令

最新版本的shell才提供printf命令,以产生格式化的输出。

语法:printf "formatstring" parameter1 parameter2 …
4.5.12 return命令

return命令的作用是使函数返回。

return命令有一个数值参数,这个参数在调用该函数的脚本程序里被看做是该函数的返回值。如果没有指定参数,return命令默认返回最后一条命令的退出码。

4.5.13 set命令

set命令的作用是为shell设置参数变量。许多命令的输出结果是以空格分隔的值,如果需要使用输出结果中的某个域,这个命令就非常有用。

<span style="font-size:14px;">#!/bin/sh
echo the date is $(date)
set $(date)
echo the month is $1
exit 0
</span>

4.5.14 shift命令

shift命令把所有参数变量左移一个位置,使$2变成$1,$3变成$2,以此类推。原来$1的值将被丢弃,而$0扔保持不变。

如果调用shift命令时指定了一个数值参数,则表示所有的参数将左移指定的次数。

<span style="font-size:14px;">#!/bin/sh
while [ “$1” != “” ]; do
echo “$1”
done
exit 0
</span>
4.5.15 trap命令

trap命令用于指定在接收到信号后将要采取的行动。trap命令的一种常见用途是在脚本程序被中断时完成清理工作。

trap -l命令用来查看信号编号及其关联的名称:

$ trap -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT
17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN
35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4
39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6
59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
trap的语法:trap commandsignal

第一个参数command是接收到指定信号时将要采取的动作。

第二个参数signal是要处理的信号名。

脚本程序通常是以上从到下的顺序解释执行的,所以你必须在你想保护的那部分代码之前指定trap命令。

重置某个信号的处理方式到期默认值,只需将command设置为-

要忽略某个信号,只需把command设置为空字符串''

<span style="font-size:14px;">#!/bin/sh
trap 'rm –f /tmp/my_tmp_file_$$’ INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
echo “Press interrupt (CTRL-C) to interrupt …”
while [ -f /tmp/my_tmp_file_$$ ]; do
echo File Exist
sleep 1
done
echo The file no longer exist
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
echo “press interrupt (control-C) to interrupt …”
while [ -f /tmp/my_tmp_file_$$ ]; do
echo File Exists
sleep 1
done
echo we never get here
exit 0
</span>
4.5.16 unset命令

unset命令的作用是从环境中删除变量或函数。这个命令不能删除shell本身定义的只读变量(如IFS)

<span style="font-size:14px;">#!/bin/sh
foo=”Hello,world”
echo $foo
unset foo
echo $foo
</span>
4.5.17 find命令

find是用于搜索文件的命令。

语法:find [path][options] [tests] [actions]

选项options
含义
-depth
-follow
-maxdepths N
-mount(或-xdev)
在查看目录本身之前先搜索目录的内容
跟随符号链接
最多搜索N层目录
不搜索其他文件系统中的目录
测试tests
含义
-atime N
-mtime N
-name pattern
-newer otherfile
-type c

-user username
文件在N天之前被最后访问过
文件在N天之前被最后修改过
文件名匹配提供的模式,pattern由引号括起
文件比otherfile文件要新
文件的类型为c,c是一个特殊类型,最常见的是d(目录)和f(普通文件)
文件的拥有者是指定的用户username
可用操作符来组合测试。大多数操作符有两种格式:短格式和长格式。

操作符,短格式
操作符,长格式
含义
!
-a
-o
-not
-and
-or
测试取反
两个测试都必须为真
两个测试有一个必须为真
动作actions
含义
-exec command
-ok command
-print
-ls
执行一条命令。该动作必须用\;字符对结束
处理前提示用户确认,其他同上
打印文件名
对当前文件使用命令ls-dils
4.5.18 grep命令

grep即GeneralRegular Expression Parser(通用正则表达式解析器)的简写。使用find命令在系统中搜索文件,而使用grep命令在文件中搜索字符串。常见的用法是在使用find命令时,将grep作为传递给-exec的一条命令。

grep命令使用一个选项、一个要匹配的模式和要搜索的文件。如果没有提供文件名,则grep搜索标准输入。

语法:grep [options] PATTERN [FILES]

选项options
含义
-c
-E
-h
-i
-l
-v
输出匹配行的数目,而不是输出匹配的行
启用扩展表达式
取消每个输出行的普通前缀,即匹配查询模式的文件名
忽略大小写
只列出包含匹配行的文件名,而不输出真正的匹配行
对匹配模式取反,即搜索不匹配行而不是匹配行
4.6 函数

语法
function_name() {
statements
}
参数:

当一个函数被调用时,脚本程序的位置参数($*、$@、$#、$1、$2等)会被替换为函数的参数。

返回值:

函数返回数字值——return命令。

函数返回字符串值——让函数将字符串保存在一个变量中,该变量可以在函数结束之后被使用。

局部变量

函数中声明局部变量——local关键字

<span style="font-size:14px;">#!/bin/sh

yes_or_no() {
echo "Is your name $* ?"
while true
do
echo -n "Enter yes or no: "
read x
case "$x" in
y | yes ) return 0;;
n | no  ) return 1;;
*       ) echo "Answer yes or no"
esac
done
}

echo "Original parameters are $*"
if yes_or_no "$1" "$2"
then
echo "Hi $1, nice name"
else
echo "Never mind"
fi

exit 0
</span>


4.7 调用另一个脚本

shell调用另一个shell脚本有三种方法:

1>fork (格式: /directory/script.sh)

fork是最普通的, 就是直接在脚本里面用/directory/script.sh来调用script.sh这个脚本.

运行的时候开一个sub-shell执行调用的脚本,sub-shell执行的时候, parent-shell还在。

sub-shell执行完毕后返回parent-shell. sub-shell从parent-shell继承环境变量.但是sub-shell中的环境变量不会带回parent-shell

<span style="font-size:14px;">$ cat 1.sh
#!/bin/bash
var=hello world
echo $var
echo '=====================array============================='
array=(1 2 3 4 5 6 78)
echo ${array[*]:1:3}
echo ${array[*]:0}
echo ${array[*]:1}
echo ${array[*]:0:4}
echo ${array[*]:0:5}
echo ${array[*]:1:4}
echo ${array[*]:1:5}
echo ${array[*] %8}
</span>
<span style="font-size:14px;">$ cat 2.sh
#!/bin/sh
echo "this file is 2.sh"
echo "call 1.sh..."
./1.sh
exit 0
$
</span>


2>exec (格式:exec /directory/script.sh)

exec与fork不同,不需要新开一个sub-shell来执行被调用的脚本. 被调用的脚本与父脚本在同一个shell内执行。但是使用exec调用一个新脚本以后, 父脚本中exec行之后的内容就不会再执行了。这是exec和source的区别。

<span style="font-size:14px;">$ cat 1.sh
#!/bin/bash
var=hello world
echo $var
echo '=====================array============================='
array=(1 2 3 4 5 6 78)
echo ${array[*]:1:3}
echo ${array[*]:0}
echo ${array[*]:1}
echo ${array[*]:0:4}
echo ${array[*]:0:5}
echo ${array[*]:1:4}
echo ${array[*]:1:5}
echo ${array[*] %8}
</span>
<span style="font-size:14px;">$ cat 2.sh
#!/bin/sh
echo "this file is 2.sh"
echo "call 1.sh..."
<strong>exec</strong> ./1.sh
exit 0
$
</span>


3>source (格式:source /directory/script.sh)

与fork的区别是不新开一个sub-shell来执行被调用的脚本,而是在同一个shell中执行. 所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中得到和使用.

<span style="font-size:14px;">$ cat 1.sh
#!/bin/bash
var=hello world
echo $var
echo '=====================array============================='
array=(1 2 3 4 5 6 78)
echo ${array[*]:1:3}
echo ${array[*]:0}
echo ${array[*]:1}
echo ${array[*]:0:4}
echo ${array[*]:0:5}
echo ${array[*]:1:4}
echo ${array[*]:1:5}
echo ${array[*] %8}
</span>
<span style="font-size:14px;">$ cat 2.sh
#!/bin/sh
echo "this file is 2.sh"
echo "call 1.sh..."
<strong>source</strong> ./1.sh
exit 0
$
</span>


5 shell调试

跟踪脚本程序中复杂错误的主要方法是设置各种shell选项。如,可以在调用shell时加上命令行选项,或是使用set命令。

命令行选项
set选项
说明
sh –n <script>

sh –v <script>

sh –x <script>

sh –u <script>
set –o noexev

set –n

set –o verbose

set –v

set –o xtrace

set –x

set –o nounset

set -u
只检查语法错误,不执行命令

在执行命令之前回显它们

在处理完命令之后回显它们

如果使用了未定义的变量,就给出出错信息
6 shell应用

Linux所有的任务都可以通过命令行来完成,而这可以通过shell来实现。

shell可以将简单的任务自动化。

shell强调易于配置、易于维护和可移植性,所以它适合编写一些执行相对简单的任务的小工具。又因为是解释执行的,所以不适合用来完成时间紧迫型和处理器忙碌型的任务。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shell变量 shell语法