Shell综述
简单的说:shell是用户和Linux操作系统之间接口,提供了与操作系统之间通讯的方式。
shell基本上是一个命令解释器,它接收用户命令(如ls等),然后调用相应的应用程序。
主要学习/bin/bash它兼容于sh,一句使用者需求,而加强的sh版本。
shell中的变量:变量的概念源于数学,在计算机中能存储计算结果,活表示值。例如:y=5x+8其中y就是变量。环境变量对bash的影响:
PATH:能不能执行某命令和PATH有关,如果在PATH中找不到相关命令,屏幕会出现command not found
普通用户PATH例子:
PATH=/sbin:/usr/java/jdk1.8.0_45-cloudera/bin:/usr/local/apache-ant/apache-ant-1.9.2/bin:/usr/local/apache-maven等
举例:读取登陆用户名:echo $LOGINAME,读取用户home目录:echo $HOME,读取当前系统默认shell:echo $SHELL
读取变量另一种格式:echo ${LOGNAME}
环境变量:使用env观察环境变量--- env|more
Linux是一个多用户多任务的操作系统,所以在Linux中不同用户具有不同的运行环境,在这样的不同环节中,可以为不同的用户指定不同的环境变量
举例:使用set或env观察环境变量
普通变量->环境变量:1、export 变量名=值,2、变量名1=值1,变量名2=值2,export 变量名1 变量名2
export var=teduhadoop -> env|grep var MAIL=/var/spool/mail/root var=teduhadoop
1)变量和值之间以一个等号"="连接(name=value)
2)变量、值和等号之间不能有空格
3)变量名称只能是英文字母、数字、下划线、但开头不能是数字。
4)变量内容若有空格符可使用双引号或者单引号将变量内容结合起来。(''单引号使特殊字符不生效,""双引号生效)
5)变量内容由其他命令提供,使用$(其它命令)
例:version=$(uname):把变量version设定值为命令uname
echo $version:和执行uname效果一样,把系统版本打印出为Linux
version=$(uname -a),echo $version 之后,则显示出Linux系统的全部内容
version=$(uname),version=$version-$(uname-p),echo $version
6)通常变量名大写为系统默认变量,自己定义变量可以使用小写,方便区分。
7)取消变量的定义:unset 变量名(如果取消系统环境变量的话,修改/etc/profile文件,否则重启后该变量还中存在)
命令定义为变量使用案例:
fname=$(uname-n)_$(date+%F)->echo $fname-> localhost.localdomain_2016-11-03
tar -zcf etc_${fname}.tar.gz /etc
8)变量总结:①全局变量:一般全大写,如环境变量②:局部变量:脚本函数中的局部变量通常使用local
③把一个命令定义成一个变量④${WEEK}day若变量和其他字符组成新的变量就必须给变量加上大括号,否则容易出错
9)数据重定向:
数据重定向就是将某个命令执行后应该要出现在屏幕上的数据,给他传输到其他的地方,例如传输到文件或是其它命令。通常执行一条命令的时候会有标准输出和标准错误输出,标准输出是指命令执行之后,传回正确信息的输出目标,标准错误输出是命令执行失败后,所传回错误信息的输出目标。
数据重定向编号:
标准输入(stdin):编号为0
标准输出(stdout):编号为1
标准错误输出(stderr):编号为2
1>:以覆盖的方法,将正确的数据输出到文件;
1>>:以累加的方法,将正确的数据输出到文件;
2>:以覆盖的方法,将错误输出的数据输出到文件;
2>>:以累加的方法,将错误输出的数据输出到文件;
举例:将ls的输出重定向到ls.log当中
# ll 1>ls.log->cat ls.log
10)命令执行判断:
$?:命令回传值,&&:若cmd1执行完毕且正确执行($?=0),则开始执行cmd2,若cmd1执行完毕且错误
($?≠0),则cmd2不执行。
||:若cmd1执行完毕且正确执行($?=0),则cmd2不执行。若cmd1执行完毕且未错误($?≠0),则开始执行cmd2
举例:如果/tmp/test存在,则创建/tmp/test/jinxf
ls /tmp/test && touch /tmp/test/jinxf:如果查询/tmp/test存在,则执行touch这个创建文件的命令
11)管道命令:
利用Linux所提供的管道符"|"将两个命令隔开,管道符左边命令的输出就会作为管道符右边命令的输入。
连续使用管道意味着第一个命令的输出会作为,第二个梦里的输入,第二个命令的输出又会作为第三个命令
的输入,以此类推。
举例:将ls的查询信息传递给grep命令进行搜索含"Music"。ls -a|grep Music
12)find命令(查找,搜索)
Linux最有用的命令之一,在一个目录(及子目录)中搜索文件,可以指定一些匹配条件,如:按文件名,
文件类型,用户甚至是时间戳查找文件。
命令格式:find [path..] [-option]
path:find命令所查找的目录路径,例如用.来表示当前目录,用/来表示系统跟目录。
options:find命令常用选项:
print:将匹配的文件输出到标准输出。
size:匹配文件大小。find./ -size 0; 显示文件大小为0的文件
name:按照文件名查找文件。find / -name demo 在/目录及子目录下面查找名字为demo的文件。
find . -name "*.java" 在当前目录及其子目录(用"."表示中查找任何扩展名为"java"的文件)
perm按照权限来查找文件:find . -perm 755 [-print] 在当前目录下查找文件权限为755的文件,
即文件所有者读,写,执行,组与其他用户可以读,执行的文件。
user按照文件所有者来查找文件,find ~ -user root [-print]在$HOME目录中查找文件属性为root
的文件。
group按照文件所属的组来查找文件。
find / -group root [-print]在目录下查找属于root的用户组文件。
mtime -n +n :按照文件的更改时间来查找文件,-n表示文件更改时间距现在n天内,+n表示文件更改时间
距现在n天前。
find / -mtime -5 print 在系统跟目录下查找更改时间在5日以内的文件。
find / -mtime +3 -print 在/目录下查找更改时间在3日以前的文件。
nogroup:查找无有效所属组的文件,即该文件所属组/etc/groups中不存在。
find / -nogroup -print
type作为find命令常用选项存在,type查找某一类型文件:
b--块设备文件。d--目录。c--字符设备文件。p--管道文件。l--符号连接文件。f--普通文件
find /etc -type d -print 在/etc目录下查找所有的目录。
find . ! -type d -print 在当前目录下查找除目录意外的所有类型文件。
find /etc -type l -print 在/etc目录下查找所有的符号链接文件。
size n:[c]查找文件长度为n的文件,带有c时表示文件长度以字节计。
find . -size +1000c -print在当前目录下查找文件长度大于1000字节的文件。
sed命令:非交互式文本处理工具,默认情况下,所有的输出行都打印到屏幕上,sed编程器逐行处理
文件(或输入),并将结果结果发送到屏幕。具体过程如下:
sed把当前正在处理的行保存在一个临时缓存区中,(也成文模式空间)然后处理临时缓冲区的行,完成后
把该行发到屏幕上,sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入再处理显示。处理完
文件最后一行,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改
源文件。sed命令格式:sed [option] "[action]" [filename]
option:h或-help 显示帮助。n仅显示script处理后的结果,V或-version显示版本信息。
e:允许输入数据应用多条sed命令进行编辑。f直接将sed的动作写在一个文件内。-f filename则可以运行
filename内的sed动作。
13)grep命令:grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)
一种强大的文件搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
grep命令的一般形式,grep [OPTIONS] PATTERN [FILE...],-?:同时显示匹配行上行下的?行。
如:grep -2 pattern filename同时显示匹配行的上下2行。
14)tail:(跟踪,监视)把某个档案文件的最后几行显示到终端上,如果该档案有更新,tail会自动刷新,确保你看到最新的
档案内容。tail [-F] [-c Number | -n Number | -m Number | -b Number | -k Number] [File]
-F该参数用户见识File文件增长。-c Number 从Number字节位置读取指定文件。
-n Number从Number行位置读取指定文件。-m Number从Number多字节字符位置读取指定文件,比如你的文件
如果包含中文字,如果指定-c参数,可能导致截断,但是使用-m会避免该问题。
例子:tail -F filename 显示filename文件的尾部内容(默认10行,相当于添加参数,-n 10 )
刷新显示在屏幕上,退出ctrl+c
tail -n 20 filename 显示filename最后20行
15)sort:sort命令默认的情况下是按照字符排序。-n:按照数值排序,-u不出现重复的行。-t指定分段的符号
-k之地你给的第几个段,-r逆向排序
例子:原始文件demo,cat demo :192.168.1.1 192.168.1.3 192.168.1.5 192.168.1.4
对文件进行排序: sort demo ---> 192.168.1.1 192.168.1.3 192.168.1.4 192.168.1.5
对文件逆序排序:sort -r demo > d1 ->192.168.1.5 192.168.1.4 192.168.1.3 192.168.1.1
对文件进行制定分隔符,并对第四个字段排序:sort -t "." -k 4 demo(以.为分割,第四段就是例子中的最后一段数字)
16)cut:在文件中负责剪切数据,命令格式:cut [-option] filename
option:-b字节,-c字符,-f提取第几列,-d按指定分隔符分割列。
例:每一行第五到第七字节:cut -b 5-7 st >demo
以点为分隔符,获取第二个字段:cut -d . -f 2 demo
17)history命令:显示全部历史,history 5 显示执行过的上5条命令,history !!运行上一条命令history !88运行第88条命令
Shell脚本编写
shell script其实就是纯文本文件,以固定的语法组织起来,可以编辑这个文件,让这个文件帮助我们一次执行多个命令。可以通过一些运算与逻辑判断来帮我们达成某些复杂的功能。shell命令执行是从上而下,从左而右执行;命令,选项与参数间的多个空格会被忽略空白行也被忽略调,tab被视为空格;如果读取一个Enter符号(CR),就尝试开始执行该行命令
#后面内容为注释。
shell的执行:
程序文件名是:/home/shell.sh,执行脚本有三种方式:
①直接执行(shell.sh文件必须具备可读与可执行(rx)的权限):
绝对路径:运行/home/shell.sh来执行指令,相对路径:cd到/home/,使用./shell.sh执行。
②source 执行: source shell.sh
③bash执行:bash shell.sh sh shell.sh
shell脚本案例:第一行#!/bin/bash,告诉系统如何执行脚本。当采用直接执行(不是用类似sh xxx.sh)时
#!/bin/bash 此行必须有,且要放在首行。
#Shows system date 除了第一行的之外#都是注释,其他为程序部分。
echo $(date + %F) exit 0,以0作为该脚本的执行返回值。执行正常退出返回0,一个脚本执行完成
exit 0 之后的shell进程可以通过$?获取执行结果:echo $?
shell脚本--数值运算:简单的加减乘除,格式:$((运算内容)),两个括号为规定
例:两数相称(交互shell脚本)
#!/bin/bash
# User inputs 2 integer numbers;program will cross these two
read -p "first number: "num1 ----把信息提示出来
read -p "second number: "num2 ----把信息提示出来
total=$(($num1*num2))
echo -e "\nThe result of $num1 * $sum2 is ==> $total" exit 0
test判断命令:使用范围:test -e demo.txt
-e该文件是否存在,-f该文件是否存在且为文件,-d该文件名是否存在且为目录
-b该文件是否存在且为一个block device 装置,-c该文件是否存在企鹅为一个character device装置
-S发u胃不好事故覅有词语不再且为一个Socket文件,-p该文件是否村子啊且为一个FIFO(pipe)文件
-L该文件是否存在且为连接文件。-nt 判断file1是否比file2新,-ot判断file1是否比file2旧
-ef 判断两个文件是否为同一个文件。
判断符号[](基本跟test相同):
[ ]脚本返利(注意[]和脚本之间保留空格)
==和!=用户比较字符串;整数比较只能使用-eq,-gt这种形式
[]中的逻辑和逻辑或使用-a和-o表示。
&& ,|| <和>操作符如果出现按在[]结构中的话,会报错。
#!/bin/bash
#this shell show user's choice
read -p "Please input(Y/N):"yn
["$yn" == "Y" -o "$yn" == "y"]&&echo "choice Yes"&&exit 0
["$yn" == "N" -o "$yn" == "n"]&&echo "choice No"&&exit 0
Shell script默认参数:
比如,ls -al其中-al就是shell脚本参数,那么我们自己写的脚本参数该如何使用?
/path/to/scriptname arg1 arg2 arg3 arg4
$0 $1 $2 $4
$0:代表脚本程序本身,$1,$2代表后面第一个参数,第二个参数,等等
$# :代表后面参数个数,以上边为例,这里显示为4
$@:代表"$1""$2""$3""$4",每个变量是肚子里的(用双引号括起来)
$*:代表"$1 $2 $3 $4"
Shell的条件判断语句:
if [ 条件判断 ] 前后要有空格
then 换行时候用then
if [ 条件判断 ]; then
条件成立执行,命令;fi 将if反过来写,就称为f结束if语句
&&代表 and || 代表or。
例子:
#!/bin/bash
#compare the size of the two numbers
a=12
b=13
if[$a -gt $b]
then
echo "yew $a>$b"
exit 0
fi
if[$a -le $b];then
echo "yew $a<=$b"
fi
多分支结构:还有一种是基于case的条件语句!!!
if [ 条件1 ];then ----条件1成立,执行指令集1
elif [ 条件2 ];then -----条件2成立,执行指令集2
else 条件都不成立,执行指令集3
fi
Shell的循环语句:
循环可以不断的执行某个程序段落,直到用户设置的条件达成位置,这被称之为不定循环,除这之外,还有另外一种已经固定要执行多少此循环这称之为固定循环。
不定循环:while do done,util do done
固定循环:for ... do done
1)while循环语句:
while [ condition条件 ] do
命令
done
例:每隔两面打印系统的负载情况。 例:使用while循环,编写shell脚本,计算1+2+3+...+100的和并输出
vim while1.sh vim while2.sh
#!/bin/bash #!/bin/bash
while true sum=0
do i=1
uptime #系统负载情况 while [$i -le 100] #while和[之间要加一个空格,true则执行
sleep 2 #休眠2秒 do
done i=$(($i+1)) #运算结果为变量赋值可以使用$((...))
ctrl+c 结束死循环。 sum=$(($sum+$i))
done
echo "the result of '1+2+3+...+100'" is $sum
2)until循环语句: --------------------->举例:
until [ condition条件 ]; do #!/bin/bash
命令 i=0
done until [ "$i" -gt 5 ] #大于5
do
let square=i*i
echo "$i * $i = $square"
let "i++"
done
3)for 循环语句: --------------------->举例:
for...do...done循环 for 男人 in 世界
语法:for 变量名 in 变量取值列表 do
do if [有房]&&[有车]&&[存款]&&[会做家务]&&[帅气]; then
命令 echo "我喜欢"
done else
提示:在此结构中"in 变量取值列表" 可省略,省略时 rm -f男人;
相当于使用for i in "$@" fi;
done
例子2:直接列出变量表所有元素,打印5,4,3,2,1
方法1:直接列出元素方法
#!/bin/bash
for num in 5 4 3 2 1 #=>需要空格隔开
do
echo $num
done
[]和[[]]区别请参照:
http://www.zsythink.net/archives/2252
在bash中,$( )与``(反引号)都是用来作命令替换的。
shell中各种括号()、(())、[]、[[]]、{}的作用:
单括号():
另开命令组——小括号中的内容会开启一个子shell独立运行;括号中以分号连接,最后一个命令不需要;各命令和括号无空格
得到命令输出——a=$(command), 等同于a=$`command`,得到命令输出传递给变量a
初始化数组——array=(a b c d)
双括号(()):
省去$符号的算术运算—— for((i=0;i<5;i++)); if (($i<5)); a=5; ((a++)) 可将 $a 重定义为6;括号内支持多个表达式用逗号分开。
C语言规则运算——$((exp)),exp为符合C语言规则的运算符,表达式
跨进制运算——二进制、八进制、十六进制运算时,输出结果全都自动转化成了十进制。如:echo $((16#5f)) 结果为95 (16进位转十进制)
单中括号[ ]:
字符串比较——==和!=
整数比较——不等于:-gt:大于;-lt :小于;-eq:等于;-ne
数组索引——array[0]
双中括号[[]]:
字符串比较——可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。
逻辑运算符——防止脚本许多逻辑错误,比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。
比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
退出码——bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。
if ($i<5)
if [ $i -lt 5 ]
if [ $a -ne 1 -a $a != 2 ]
if [ $a -ne 1] && [ $a != 2 ]
if [[ $a != 1 && $a != 2 ]]
for i in $(seq 0 4);do echo $i;done
for i in `seq 0 4`;do echo $i;done
for ((i=0;i<5;i++));do echo $i;done
for i in {0..4};do echo $i;done
大括号{}:
创建匿名函数——不会新开进程,括号内变量余下仍可使用。括号内的命令间用分号隔开,最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格。特殊替换——${var:-string},${var:+string},${var:=string},${var:?string}
特殊替换——${var:-string},${var:+string},${var:=string},${var:?string}
①${var:-string}和${var:=string}:若变量var为空,则用在命令行中用string来替换${var:-string},否则变量var不为空时,则用变量var的值来替换${var:-string};不同之处是${var:=string}常用于判断var是否赋值,没有的话则给var赋上一个默认值。
② ${var:+string}:替换规则和上面的相反,即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量 var的值,即空值。(因为变量var此时为空,所以这两种说法是等价的)
③${var:?string}:替换规则为:若变量var不为空,则用变量var的值来替换${var:?string};若变量var为空,则把string输出到标准错误中,并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。
注意:在上面这五种替换结构中string不一定是常值的,可用另外一个变量的值或是一种命令的输出。
模式匹配替换——${var%pattern},${var%%pattern},${var#pattern},${var##pattern}
# 是去掉左边(在键盘上#在$之左边);% 是去掉右边(在键盘上%在$之右边);#和%中的单一符号是最小匹配,两个相同符号是最大匹配。
第一种模式:${variable%pattern}。shell在variable中查找,看它是否一给的模式pattern结尾,如果是,把variable去掉右边最短的匹配模式
第二种模式: ${variable%%pattern},这种模式时,shell在variable中查找,看它是否一给的模式pattern结尾,如果是,把variable中去掉右边最长的匹配模式
第三种模式:${variable#pattern} 这种模式时,shell在variable中查找,看它是否一给的模式pattern开始,如果是,把variable中去掉左边最短的匹配模式
第四种模式: ${variable##pattern} 这种模式时,shell在variable中查找,看它是否一给的模式pattern结尾,如果是,把variable中去掉左边最长的匹配模式
这四种模式中都不会改变variable的值,其中,只有在pattern中使用了*匹配符号时,%和%%,#和##才有区别。结构中的pattern支持通配符,*表示零个或多个任意字符,?表示仅与一个任意字符匹配,[...]表示匹配中括号里面的字符,[!...]表示不匹配中括号里面的字符。
技巧小结
字符串比较用双中括号[[ ]];算数比较用单中括号[ ]——左右留空格
算数运算用双小括号(( )) ;shell命令及输出用小括号( )——左右不留空格
快速替换用花括号{ }——左右留空格
反单引号起着命令替换的作用` `