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

常用Shell知识总结

2016-11-30 18:32 190 查看

Shell

本文档主要介绍Shell的相关知识,部分内容设计Linux的知识;

Shell
Shell 资源列表

Shell 基本介绍

Shell 变量
变量类型

变量替换

Shell特殊符号
双引号

反斜线

单引号

转义字符

注释字符

Shell中的字符串
获取字符串长度

提取子字符串

Shell 数组
定义数组

读取数组

获取数组的长度

命令替换

运算符
算数运算符

条件测试

流程控制
条件语句

多路条件语句

for循环

while循环

Until 循环

循环控制

Shell函数
函数定义

函数返回值

函数参数

Shell输入输出重定向

正则匹配

常用命令
查看程序完整执行路径

查看文件大小

编码转换

序列生成

进程管理

echo 命令

find

grep

命令转后台执行的方法

查看系统

脚本中包含其他shell脚本

shell脚本执行的目录

排序命令 sort

crontab 命令的使用说明

Shell 资源列表

http://c.biancheng.net/cpp/shell/

http://www.runoob.com/linux/linux-shell-func.html

Shell 基本介绍

Unix/Linux上常见的Shell脚本解释器有bash、sh、csh、ksh等,习惯上把它们称作一种Shell。我们常说有多少种Shell,其实说的是Shell脚本解释器。

bash是Linux标准默认的shell

注意:bash是 Bourne Again Shell 的缩写,是linux标准的默认shell ,它基于Bourne shell,吸收了C shell和Korn shell的一些特性。bash完全兼容sh,也就是说,用sh写的脚本可以不加修改的在bash中执行。

Shell 变量

定义变量时,变量名不加美元符号($);

注意,等号左右不能有空格,这可能和你熟悉的所有编程语言都不一样;

使用一个定义过的变量,只要在变量名前面加美元符号($)即可;变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界;推荐给所有变量加上花括号,这是个好的编程习惯。

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

#!/bin/bash
myUrl="http://see.xidian.edu.cn/cpp/shell/"
readonly myUrl
myUrl="http://see.xidian.edu.cn/cpp/danpianji/"


使用 unset 命令可以删除变量

变量类型

运行shell时,会同时存在三种变量:

1) 局部变量

局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。

2) 环境变量

所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。

3) shell变量

shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

变量含义
$0当前脚本的文件名
$n传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$#传递给脚本或函数的参数个数。
$*传递给脚本或函数的所有参数。
$@传递给脚本或函数的所有参数。被双引号(” “)包含时,与 $* 稍有不同,下面将会讲到。
$?上个命令的退出状态,或函数的返回值。
$$当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID
∗和@ 都表示传递给函数或脚本的所有参数,不被双引号(” “)包含时,都以”$1” “$2” … “$n” 的形式输出所有参数。

但是当它们被双引号(” “)包含时,”$*” 会将所有的参数作为一个整体,以”$1 $2 … $n”的形式输出所有参数;

“$@” 会将各个参数分开,以”$1” “$2” … “$n” 的形式输出所有参数。

变量替换

变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值

可以使用的变量替换形式:

${var}

获取变量原先的值;

${var:-wold}

如果变量var为空或者已经被删除(unset), 那么返回word,但不改变var的值;

${var:=word}

如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word;

${var:?message}

如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。若此替换出现在Shell脚本中,那么脚本将停止运行;

${var:+word}

如果变量 var 被定义,那么返回 word,但不改变 var 的值

Shell特殊符号

双引号

” “: 由双引号括起来的字符,除$,倒引号(` `)和反斜线 ( / )外,其他均当做普通字符。这三仍保留特殊功能!

其中 ${变量名字} 表示变量替换;

反斜线

\ 仅当后面字符是 $,`, “,/ 或换行符之一时,/才是转义字符,告诉shell,不要对后面那个字符进行特殊处理,只当做普通字符

单引号

由单引号括起来的字符都当做普通字符处理;

单引号字符串中的变量是无效的;

单引号字串中不能出现单引号(对单引号使用转义符后也不行), 因为转义字符也会被当成普通字符的;

转义字符

\b:退格

\c:忽略echo最后默认的换行符,同时忽略\c后的字符

注释字符

Shell中的注释,使用字符#, 在shell中没有多行注释命令;

Shell中的字符串

字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似。

获取字符串长度

echo ${#variable}

提取子字符串

string="alibaba is a great company"
echo ${string:1:4} #输出liba


Shell 数组

Shell在编程方面比Windows批处理强大很多,无论是在循环、运算。

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。

定义数组

# 在Shell中,用括号来表示数组,数组元素用“空格”(空格或者回车)符号分割开。定义数组的一般形式为:

array_name=(value1 ... valuen)
或者
array_name=(
value0
value1
value2
value3
)

array_name=(value0 value1 value2 value3)
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
# 可以不使用连续的下标,而且下标的范围没有限制。


读取数组

读取数组元素值的一般格式是:

${array_name[index]}

# 使用@ 或 * 可以获取数组中的所有元素
${array_name[*]}
${array_name[@]}


获取数组的长度

#取得数组元素的个数
length=${#array_name[@]}
#或者
length=${#array_name[*]}
#取得数组单个元素的长度
lengthn=${#array_name
}


命令替换

命令替换,可以采用两种方式:

倒引号

$()

由倒引号或者$() 括起来的字符串被shell解释为命令行,执行时,shell会先执行该命令行,以他的标准输出结果取代整个倒引号部分

运算符

Bash 支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。

算数运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 bc, awk 和 expr,expr 最常用。

expr 是一款表达式计算工具,使用它能完成表达式的求值操作

#!/bin/bash
val=`expr 2 + 2`
echo "Total value : $val"


两点注意:

表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。

完整的表达式必须使用命令替换的形式,注意这个字符不是常用的单引号,在 Esc 键下边。

bc 是Linux的一个独立的计算程序,可以单独使用, 嵌入Shell脚本中使用,可以发挥较大的功用;

#!/bin/bash
echo "23 + 23" | bc   # 直接计算命令
echo "scale=4; 12/5" | bc  # 计算浮点数的命令

# 计算多行表达式的工具
result=$(
bc << EOF
scale=4
12 / 5
EOF)


条件测试

测试命令有两种结构,一种是用test命令进行测试,结构如下:

test expression 其中,条件expression是一个表达式,该表达式可为数字、字符串、文本和文件属性的比较,同时加入各种算术、字符串、文本等运算符。

关系运算符

运算符说明举例
-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 true。
-ne检测两个数是否相等,不相等返回 true。[ $a -ne $b ] 返回 true。
-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。
-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。
-ge检测左边的数是否大等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。
-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。
* 布尔运算符列表

运算符说明举例
!非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a与运算,两个表达式都为 true 才返回 true。[ $a -lt 20 -a $b -gt 100 ] 返回 false。
* 字符串运算符列表

运算符说明举例
=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
!=检测两个字符串是否相等,不相等返回 true。[ $a != $b ] 返回 true。
-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
-n检测字符串长度是否为0,不为0返回 true。[ -n $a ] 返回 true。
str检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。
* 文件测试运算符列表

操作符说明举例
-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false
-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -b $file ] 返回 false
-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true
-g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false
-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false
-p file检测文件是否是具名管道,如果是,则返回 true。[ -p $file ] 返回 false
-u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false
-r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true
-w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true
-x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true
-s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true
-e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true

流程控制

条件语句

if [ expression ];
then
Statement(s) to be executed if expression is true
fi

if [ expression ];
then
Statement(s) to be executed if expression is true
else
Statement(s) to be executed if expression is not true
fi

if [ expression 1 ];
then
Statement(s) to be executed if expression 1 is true
elif [ expression 2 ];
then
Statement(s) to be executed if expression 2 is true
elif [ expression 3 ];
then
Statement(s) to be executed if expression 3 is true
else
Statement(s) to be executed if no expression is true
fi


多路条件语句

case $val in
pattern1)
command1
command2
command3
;;
pattern2)
command1
command2
command3
;;
*)
command1
command2
command3
;;
esac


case工作方式如上所示。取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。

取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

for循环

for循环一般格式为:

for var in vals
do
command1
command2
...
commandN
done


列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。

in 列表是可选的,如果不用它,for 循环使用命令行的位置参数。

while循环

while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

while command
do
Statement(s) to be executed if command is true
do


命令执行完毕,控制返回循环顶部,从头开始直至测试条件为假。

Until 循环

until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反。一般while循环优于until循环,但在某些时候,也只是极少数情况下,until 循环更加有用。

until 循环格式为:

until command
do
Statement(s) to be executed until command is true
done


command 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

循环控制

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,像大多数编程语言一样,Shell也使用 break 和 continue 来跳出循环。

break命令

break命令允许跳出所有循环(终止执行后面的所有循环);

continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环;

Shell函数

函数可以将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高。像其他编程语言一样,Shell 也支持函数。Shell 函数必须先定义后使用

函数定义

Shell 函数的定义格式如下:

function_name () {
list of commands
[ return value ]
}


如果你愿意,也可以在函数名前加上关键字 function:

function function_name () {
list of commands
[ return value ]
}


函数返回值

函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值。

Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:“numeric argument required”。

如果一定要让函数返回字符串,那么可以先定义一个变量,用来接收函数的计算结果,脚本在需要的时候访问这个变量来获得函数返回值。

调用函数只需要给出函数名,不需要加括号。

函数返回值在调用该函数后通过 $? 来获得。

function return_val()
{
ls *
return $?
}
return_val
echo $?

function return_val()
{
ls *
echo "hello world"
}
re_val=$(return_val)
echo re_val


像删除变量一样,删除函数也可以使用 unset 命令,不过要加上 .f 选项,如下所示:

$unset .f function_name

函数参数

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如$1 表示第一个参数,$2表示第二个参数…

注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

另外,还有几个特殊变量用来处理参数,前面已经提到:

特殊变量说明
$#传递给函数的参数个数。
$*显示所有传递给函数的参数。
$@与$*相同,但是略有区别,请查看Shell特殊变量。
$?函数的返回值。

Shell输入输出重定向

Unix 命令默认从标准输入设备(stdin)获取输入,将结果输出到标准输出设备(stdout)显示。一般情况下,标准输入设备就是键盘,标准输出设备就是终端,即显示器。

重定向深入讲解

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。

标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。

标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

全部可用的重定向命令列表

命令说明
command > file将输出重定向到 file。
command < file将输入重定向到 file。
command >> file将输出以追加的方式重定向到 file。
n > file将文件描述符为 n 的文件重定向到 file。
n >> file将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m将输出文件 m 和 n 合并。
n <& m将输入文件 m 和 n 合并。
<< tag将开始标记 tag 和结束标记 tag 之间的内容作为输入。
像其他语言一样,Shell 也可以包含外部脚本,将外部脚本的内容合并到当前脚本。

Shell 中包含脚本可以使用:

. filename



source filename

两种方式的效果相同,简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格。

正则匹配

不要讲正则匹配与Shell中文件名匹配相混淆;

* 任意字符串
? 单个字符
[ ] 其中包含的字符,只是占据一个字符位置;
[! ]非其中包含的字符


常用命令

查看程序完整执行路径

ps -few | grep "program_id"


查看文件大小

du -sh file/floder


编码转换

iconv -f encoding -t encodeing  [input_file]  -o output_file


序列生成

# 用户产生序列生成器,主要用于控制循环的次数;
seq [option] Last
seq [option] First Last
seq [option] First Increment Last
-w: --equal-width  讲每个输出设置成等宽;

seq -w 5 -1 1  # 5 4 3 2 1


进程管理

kill -0 PID
#向某一进程发送一个无效的信号,如果该进程存在(能够接收信号),echo $?为0,否则为1,已证明此进程是否存在;

kill -9 PID
# fource to kill the pid


echo 命令

-n 不要在最后自动换行

-e 打开反斜杠转义。若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:

\a 发出警告声;

\b 删除前一个字符;

\c 最后不加上换行符号;

\f 换行但光标仍旧停留在原来的位置;

\n 换行且光标移至行首;

\r 光标移至行首,但不换行;

\t 插入tab;

\v 与\f相同;

\ 插入\字符;

\nnn 插入nnn(八进制)所代表的ASCII字符;

-E 取消反斜杠ESC转义 (默认)

find

find pathname -options [-print ]

find pathname -name  filename
find pathname -size -num[cwbkMG]  #查找小于 num 的文件;
find pathname -size +num[cwbkMG]  #查找大于 num 的文件;
find pathname -size num[cwbkMG]   #查找大小等于num的文件;


grep

grep  pattern file  #在文件中查找pattern,配合wc可以获取匹配的个数;
grep -rn "str" ./ # 查找当前目录下所有文件中存在str的文件,并显示行号;


命令转后台执行的方法

example:
scp souruce server:destimation
input your passwd;
ctrl + z;
jobs
bg num
that is ok


这种方法存在缺陷,就是如果终端中断,那么程序也会跟着中断;

查看系统

cat /etc/issue

Linux szjjh-test-nlp03.szjjh01.baidu.com 2.6.9_5-9-0-0 #1 SMP Wed Jun 23 14:03:19 CST 2010 x86_64 x86_64 x86_64 GNU/Linux

Red Hat Enterprise Linux AS release 4 (Nahant Update 3)

http://blog.163.com/william_djj@126/blog/static/351665012013611251839/

脚本中包含其他shell脚本

source shell.sh

. shell.sh

shell脚本执行的目录

如果脚本中执行的时候,遇到相对路径都是相对命令执行时所在的路径;

排序命令 sort

LC_ALL=C 设置编码环境

-t 指定分隔符 $’\t’ 按照\t 分割;

-n 将字符串当做数字处理;

-r 逆序排列;

-u 去除重复;

如果你想把排序结果输出到原文件中,用重定向,会出现问题,会讲源文件变为空;

-o 可以将输出定想到指定的文件;

注意sort去重,是按照排序的字段来进行的;

crontab 命令的使用说明

cron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业。由于Cron 是Linux的内置服务,但它不自动起来,可以用以下的方法启动、关闭这个服务:

/sbin/service crond start //启动服务
/sbin/service crond stop //关闭服务
/sbin/service crond restart //重启服务
/sbin/service crond reload //重新载入配置
你也可以将这个服务在系统启动的时候自动启动:
在/etc/rc.d/rc.local这个脚本的末尾加上:
/sbin/service crond start
现在Cron这个服务已经在进程里面了,我们就可以用这个服务了,Cron服务提供以下几种接口供大家使用:

1、直接用crontab命令编辑
cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:
crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数
crontab -l //列出某个用户cron服务的详细内容
crontab -r //删除某个用户的cron服务
crontab -e //编辑某个用户的cron服务

分钟 (0-59)
小時 (0-23)
日期 (1-31)
月份 (1-12)
星期 (0-6)//0代表星期天
除了数字还有几个个特殊的符号就是"*"、"/"和"-"、",",*代表所有的取值范围内的数字,"/"代表每的意思,"*/5"表示每5个单位,"-"代表从某个数字到某个数字, ","分开几个离散的数字。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shell