linux-shell详解

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&lt;5)        
if [ $i -lt 5 ]        
if [ $a -ne 1 -a $a != 2 ]        
if [ $a -ne 1] &amp;&amp; [ $a != 2 ]        
if [[ $a != 1 &amp;&amp; $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&lt;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命令及输出用小括号( )——左右不留空格
快速替换用花括号{ }——左右留空格
反单引号起着命令替换的作用` `

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戰士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值