wendy003
命令执行的判断依据:;.&& ||
//cmd;cmd (不考虑指令相关性的连续指令下达),比如先执行两次sync同步化写入磁盘后才shutdown
sync;sync;shutdown -h now
// $?(指令回传值) 与 ## 或 ||
$? =0,若前一个指令执行的结果为正确,在linux底下会回传一个 $?=0 的值
ls /tmp/abc && touch /tmp/abc/hehe //ls显示找不到对应的目录,touch还未执行
// ||
ls /tmp/abc || mkdir /tmp/abc // 不存在该文件
ll /tmp/abc //上面指令执行mkdir命令
指令依序执行的关系示意图:
1.上方线段为不存在/tmp/abc,回传$?!=0,因为||执行mkdir,回传$?=0,又遇到&&,执行touch
2.下方线段为存在/tmp/abc,回传$?=0,因为||,所以不执行mkdir,$?=0往后继续回传,因为又遇到&&,执行touch
6 管线命令(pipe)
管线命令 | 仅能处理经由前面一个指令传来的正确信息,也就是stdout的信息,对于stderr并没有直接处理的能力。
管线命令的处理示意图:在每个管线后面接的第一个数据必定是指令,而且这个指令必须要能够接受stdin的数据才行,称为管线命令。
比如less,more,head,tail等都是可以接收stdin的管线命令,至于例如ls,cp,mv等就不是管线命令。
6.1 截取命令:cut、grep
截取命令:cut,grep。就是将一段数据经过分析后,取出想要的,或者经由分析关键词,取得我们所想要的那一行。截取信息通常是针对一行一行来分析的。
//cut的用途:在于将同一行里面的数据进行分解,即将一行讯息当中,取出某部分我们想要的。
//cut用于有特定分隔字符,cut -d '分隔字符' -f fields
-d:后面接分隔字符,与-f一起使用
-f:依据-d的分隔字符将一段讯息分割成为数段,用-f取出第几段
-c:以字符的单位取出固定字符区间,同时可以处理具有格式的输出数据,比如第12-20的字符,就是:cut -c 12-20
//cut -c 字符区间
[wendy@cs011 jdk]$ echo $PATH
/opt/wendy/local/jdk/jdk1.8.0_152/bin:/home/wendy/.nvm/versions/node/v10.18.1/bin:/usr/local/bin:/usr/bin:/usr/local/sbin
[wendy@cs011 jdk]$ echo $PATH | cut -d ':' -f 4 //以:作为分隔符,列出第四的内容
/usr/bin
[wendy@cs011 jdk]$ echo $PATH | cut -d ':' -f 4,5 //以:作为分隔符,列出第四、第五的内容
/usr/bin:/usr/local/sbin
//grep:分析一行讯息,grep [-acinv][--color=auto]'搜寻字符串' filename
-a:将binary文件以test文件的方式搜寻数据
-c:计算找到'搜寻字符串'的次数
-i:忽略大小写的不同,所以大小写视为相同
-n:顺便输出行号
-v:反向选择
--color=auto:可以将找到的关键词部分加上颜色的显示.
last | grep 'root'| cut -d '' -f1 //在last的输出讯息中,只要有root就取出,并且以空为分隔符,仅取第一栏。在取出root之后,利用上个指令cut的处理,就能够仅取得第一栏。
last | grep -v 'root' //只要没有root的就取出
last | grep 'root' //将last当中,有出现root的那一行取出来
6.2 排序命令:sort、uniq、wc
场景:计算一次数据里头的相同型态的数据总数,使用last可以查得这个月份有登入主机者的身份。
sort:排序,根据不同数据型态来排序,比如数字与文字的排序,此外排序的字符与语系的编码有关。
uniq:排序完成之后,想要将重复的资料仅列出一个显示。
wc:统计/etc/man.config文件里面有多少字、多少行、多少字符。
//排序命令:sort,wc,uniq。sort [-fbMnrtuk][file or stdin],sort进行排序,可以根据不同的数据型态来排序,比如数字与文字的排序。
-f:忽略大小写的差异,例如A与a 视为编码相同
-b:忽略最前面的空格符部分
-M:以月份的名字来排序,例如JAN,DEC等等的排序方法
-n:使用纯数字进行排序(默认是以文字型态来排序的)
-r:反向排序
-u:就是uniq,相同的数据中,仅出现一行代表
-t:分隔符,预设是用tab键来分隔
-k:以哪个区间(field)来进行排序
//sort排序,个人账号都记录在/etc/passwd下,并将账号进行排序,默认是以第一个数据来排序,从a-z进行显示
[wendy@cs011 jdk]$ cat /etc/passwd |sort
abrt:x:173:173::/etc/abrt:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
chrony:x:996:994::/var/lib/chrony:/sbin/nologin
//sort排序,在/etc/passwd内容是以:来分隔的,以第三栏来排序
[wendy@cs011 jdk]$ cat /etc/passwd |sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
haishu:x:1000:1000::/home/wendy:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
//uniq [-ic],排序完成,将重复的资料仅列出一个显示.-c表示reboot登录有12次,root登录有41次。wtmp与空白都是last的默认字符,那两个可以忽略。
-i:忽略大小写字符的不同
-c:进行计数
[wendy@cs011 jdk]$ last |cut -d ' ' -f1 | sort | uniq -c
12 reboot
41 root
1 wtmp
//wc [-lwm],/etc/profile里面到底有多少行、字数、字符数
-l:仅列出行
-w:列出多少字
-m:多少字符
[wendy@cs011 jdk]$ cat /etc/profile | wc
80 261 1903
6.3 双向重导向:tee
tee:将数据流的处理过程中的某段讯息存下来。tee会同时将数据流分送到文件与屏幕里去。输出到屏幕的,就是stdout。
tee的工作流程示意图:
//tee:同时将数据流分送到文件去与屏幕(screen),而输出到屏幕的,其实就是stdout
//tee [-a] file
-a:以累加(append)的方式,将数据加入file当中
last | tee last.list | cut -d " " -f1 //让我们将last的输出存一份到last.list文件中
ls -l /home | tee ~/homefile |more //将ls的数据存一份到~/homefile,同时屏幕也有输出讯息。
ls -l / | tee -a ~/homefile |more //tee后接的文件会被覆盖,若加上-a 这个选项则能将讯息累加。
6.4 字符转换命令:tr、col、join、paste、expand
tr:可以用来删除一段信息当中的文字,或者是进行文字信息的替换。
col:用来简单的处理将tab键取代称为空格键。
join:处理两个文件之间的数据,主要是处理在两个文件当中,有相同数据的那一行,才将他加在一起。
paste:必须要比对两个文件的数据相关性。paste就直接将两行贴在一起,且中间以tab键隔开。
//字符转换命令:tr,col,join,paste,expand
//tr 可以用来删除一段讯息当中的文字,或者是进行文字讯息的替换,tr [-ds] SET1 ...
-d:删除讯息当中的[SET1]这个字符串
-s:取代掉重复的字符
//将last输出的讯息中,所有的小写变成大写字符
[wendy@cs011 jdk]$ last | tr '[a-z]' '[A-Z]'
//将/etc/passwd输出的讯息中,将冒号(:)删除
源文件显示:
[wendy@cs011 ~]$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[wendy@cs011 ~]$ cat /etc/passwd | tr -d ':'
rootx00root/root/bin/bash
binx11bin/bin/sbin/nologin
daemonx22daemon/sbin/sbin/nologin
//col [-xb]
-x:将tab键转换成对等的空格键
-b:在文字内有反斜杠(/)时,仅保留反斜杠最后接的那个字符
cat /etc/profile | col -x | cat -A |more
//join [-ti12] file1 file2
-t:join默认以空格符分隔数据,并且比对[第一个字段]的数据,如果2个文件相同,则将两笔数据联成一行,且第一个字段放在第一个
-i:忽略大小写的差异
-1:数字的1,代表第一个文件要用那个字段来分析
-2:代表第二个档案要用那个字段来分析
test.txt:001:wendy:004、002:wendy:005、003:wendy:006、004:wendy:001、005:wendy:002、006:wendy:003
test001.txt:001:002、002:003、003:004、004:005
//将test.txt与test001.txt相关数据整合成一栏,结果显示为:
[wendy@cs011 develop]$ head -n 10 ./test.txt ./test001.txt
==> ./test.txt <==
001:wendy:004
002:wendy:005
003:wendy:006
004:wendy:001
005:wendy:002
006:wendy:003
==> ./test001.txt <==
001:002
002:003
003:004
004:005
//join使用之前,你所需要处理的文件应该要事先经过排序处理,将两个文件第一个字段相同者整合成一行,第二个文件的相同字段并不会显示
[wendy@cs011 develop]$ join -t ':' ./test.txt ./test001.txt
001:wendy:004:002
002:wendy:005:003
003:wendy:006:004
004:wendy:001:005
//paste [-d] file1 file2 ,选项与参数
-d:后面可以接分隔字符,预设以tab来分隔
-:如果file部分写成-,表示来自stdin的文件
eg:
//将test.txt与test001.txt同一行贴在一起,同一行中间以tab按键隔开
[wendy@cs011 develop]$ paste test.txt test001.txt
001:wendy:004 001:002
002:wendy:005 002:003
003:wendy:006 003:004
004:wendy:001 004:005
005:wendy:002
006:wendy:003
//expand [-t] file,选项要参数。在将tab按键转成空格键
-t:后面可以接数字,一个tab按键可以用8个空格键取代
6.5 分割命令:split
场景:文件太大,导致无法复制,split可以帮你将一个大文件,依据文件大小或行数来分隔,就可以将大文件分割成小文件。
//split分割命令,split [-bl] file PREFIX
-b:后面可接文件大小,可加单位,例如b,k,m。
-l:以行数来进行分割。
PREFIX:代表前导符的意思,可作为分割文件的前导文字。
//分割命令split,那个文件名可以随意取,只要写上前导文件,小文件就会以xxxaa,xxxab,xxxac等方式来建立小文件的。
[wendy@cs011 develop]$ split -b 30 ./test.txt test.txt
[wendy@cs011 develop]$ ll -k test.txt*
-rw-rw-r-- 1 wendy wendy 84 Apr 27 10:55 test.txt
-rw-rw-r-- 1 wendy wendy 30 Apr 27 11:20 test.txtaa
-rw-rw-r-- 1 wendy wendy 30 Apr 27 11:20 test.txtab
-rw-rw-r-- 1 wendy wendy 24 Apr 27 11:20 test.txtac
//将三个上面的三个小文件合成一个文件,文件名为testback
[wendy@cs011 develop]$ cat test.txta* >> test.txtback
[wendy@cs011 develop]$ ll
-rw-rw-r-- 1 wendy wendy 84 Apr 27 10:55 test.txt
-rw-rw-r-- 1 wendy wendy 30 Apr 27 11:20 test.txtaa
-rw-rw-r-- 1 wendy wendy 30 Apr 27 11:20 test.txtab
-rw-rw-r-- 1 wendy wendy 24 Apr 27 11:20 test.txtac
-rw-rw-r-- 1 wendy wendy 84 Apr 27 11:26 test.txtback
6.6 参数代换:xargs
xargs:x是加减乘除的乘号,args则是arguments(参数)。xargs参数产生某个指令的参数。xargs可以读入stdin的数据,并且以空格符或断行字符作为分隔,将stdin的资料分隔成为arguments。
//xargs [-0epn] command,选项与参数
-0:输入的stdin含有特殊字符,例如'\,空格键等字符时,这个-0参数还原成一般字符。
-e: 这个是EOF(end of file ),后面可以接一个字符串,当xargs分析到这个字符串时,就会结束继续工作。
-n:后面接次数,每次command指令执行时,要使用几个参数。当后面没有参数时,默认是以echo来进行输出。
-p:在执行每个指令的argument时,都会询问使用者的意思
[wendy@cs011 ~]$ cut -d: -f1 < /etc/passwd | sort | xargs echo
abrt adm bin chrony daemon dbus ftp games gluster haishu halt libstoragemgmt lp mail named nobody ntp operator polkitd postfix root rpc shutdown sshd sync systemd-bus-proxy systemd-network tcpdump tss
核心在内存中受保护,需要透过shell 将我们输入的指令与核心沟通
学习shell的原因:一致性;速度快;shell主导
系统合法的shell均写在/etc/shells文件中
用户默认登录取得的shell记录在/etc/passwd的最后一个字段
bash功能的主要有:命令修复能力;命令与档案补全功能;命令别名设定功能;工作控制、前景背景控制;程序后脚本;通配符
type可以用来找到执行指令为何种类型
变量就是以一组文字或符号等,来取代一些设定或者是一串保留的数据
变量主要有环境变量与自定义变量,或称为全局变量与局部变量,使用env、export可观察环境变量,export可以将自定义变量转成环境变量
set可以观察目前bash环境下的所有变量;$?为变量,是前一个指令执行完毕后的回传值,回传值=0表示执行成功
locale可以观察语系资料;可用read让用户由键盘输入变量的值,ulimit可用以限制用户使用系统的资源情况
bash的配置文件主要分为login shell与non-login shell.login shell主要读取/etc/profile与~/.bash_profile,non-login shell则仅读取~/.bashrc
通配符主要有:*?[]等待
数据流重导向透过>,2>,<之类的符号将输出的信息转到其他文件或装置去
连续命令的下达:&& 、||
管线命令的重点:管线命令仅会处理stdout,对于stderr会予以忽略,同时管线命令必须要能够接受来自前一个指令的数据成为stdin继续处理。
管线命令主要包含:cut、grep、sort、wc、uniq、tee、tr、col、join、paste、expand、split、xargs。
7 正规表示法与文件格式化处理
正规表示法[Regular Expression,RE,常规表示法]:处理字符串的方法,以行为单位来进行字符串的处理行为。透过一些特殊字符的排列,用以搜寻/取代/删除一列或多列文字字符串[简单说,正则表示法就是用在字符串的处理上面的一项表达式,是一个字符串处理的标准依据]。比如:vi,sed,awk等等。只要工具程序支持正规表示法,该工具程序就可以用来作为正规表示法的字符串处理之用。
正规表示法的字符串表示方式依照不同的严谨程度分为:基础正规表示法与延伸正规表示法。
基础正规表示法:处理字符串的一种表示方式,对字符排序有影响的语系数据就会对正规表示法的结果有影响。比如grep.
延伸型正规表示法:除了简单的一组字符串处理之外,还可以作群组的字符串处理。
常见的正规表示法工具有:grep、sed、awk、vim。printf可以透过一些特殊符号来将数据进行格式化输出,awk可以使用字段为依据,进行数据的重新整理与输出。
7.1 grep工具
grep作用:字符串数据比对,将符合用户需要的字符串打印出来。
grep在数据中查寻一个字符串时,是以"整行"为单位来进行数据的截取。比如一个文件内有10行,其中有2行是你所搜寻的字符串,则将那两行显示在屏幕上,其他丢弃。
在关键词显示方面,用--color=auto来将关键词部分使用颜色进行显示。
//grep [-A][-B][--color=auto] '搜寻字符串' filename
-A:after的意思,除了列出该行外,后续的n行也列出来
-B:before的意思,除了列出该行外,前面的n行也列出来
--color=auto 可将正确的那个截取数据列出颜色
//用dmesg列出核心信息,再以grep 找到eth所在行的前2行与后三行也一起进行显示
dmesg | grep -n -A3 -B2 --color=auto 'eth'
test.txt文件内容:001:wendy:004、002:wendy:005、003:wendy:006、004:wendy:001、005:wendy:002、006:wendy:003
//1.搜寻特定字符串,比如从test.txt文件当中取得001这个特定字符串
[wendy@cs011 develop]$ grep -n '001' test.txt
1:001:wendy:004
4:004:wendy:001
//2.反向选择,比如从test.txt文件当中,当该行没有'001'这个字符串时才显示在屏幕上
eg1:
[wendy@cs011 develop]$ grep -vn '001' test.txt
正规表示法与通配符完全不一样,通配符代表的是bash操作接口的一个功能,但正规表示法则是一种字符串处理的表示方式。
使用grep或其他工具进行正规表示法的字符串比对时,编码问题会有不同的状态,设置LANG等变量设定为C或是en的英文语系,可利用特殊符号[:upper:]来替代编码范围。
grep与egrep在正规表示法里面常见的两支程序,其中egrep更支持正规表示法的语法。
grep -v '^$' test.txt | grep -v '^#'
//egrep进行简化,透过群组功能|来进行一次搜寻。grep -E = egrep 的写法
egrep -v '^$ | ^#' test.txt
// sed [-nefr] [动作],选项与参数说明
-n:使用安静(silent)模式。在一般sed用法中,所有来自STDIN的数据一般都会被列出屏幕上。
-e:直接在指令列模式上进行sed的动作编辑。
-f:直接将sed的动作写在一个文件内,-f filename则可以执行filename内的sed动作
-r:sed的动作支持的是延伸型正规表示法的语法。(预设是基础正规表示法语法)
-i:直接修改读取的文件内容,而不是由屏幕输出。
[动作说明]:[n1[,n2]]function
n1,n2:不一定存在,代表选择进行动作的行数,比如在10-20行之间进行,则[10,20][动作行为]
function有如下参数:
a:新增,a的后面接字符串,在新行进行显示
c:替换,接字符串,可以在n1,n2之间替换
i:插入,接字符串,新行出现
p:打印,与参数sed -n一起使用
s:替换,直接替换,比如1,20s/old
eg1:以行为单位的新增/删除功能
//将etc/passwd的内容列出并且打印行号,请将2~5行删除。
[wendy@cs011 develop]$ nl /etc/passwd | sed '2,5d'
//只要删除第2行。
[wendy@cs011 develop]$ nl /etc/passwd | sed '2d'
//删除第3行到最后一行,$代表最后一行!
[wendy@cs011 develop]$ nl /etc/passwd | sed '3,$d'
//新增,在a后面加上的字符串就已将出现在第二行后面。
[wendy@cs011 develop]$ nl /etc/passwd | sed '2a drink tea'
//新增,加上的字符串就已将出现在第二行前面,由a改为i即可。
[wendy@cs011 develop]$ nl /etc/passwd | sed '2i drink tea'
eg2:以行为单位的取代与显示功能
//将etc/passwd中的第2~5行的内容替换[2,5c]:No 2-5number
[wendy@cs011 develop]$ nl /etc/passwd | sed '2,5c No 2-5number'
eg3:以行为单位的显示功能
//列出文件内的第5-7行,sed '5,7p'(5-7行会重复输出),所以一般与-n一起使用
[wendy@cs011 develop]$ nl /etc/passwd | sed -n '5,7p'
eg4:部分数据的搜寻并取代的功能
//除了整行的处理模式之外,sed还可以用来行为单位进行部分数据的搜寻并取代的功能
//sed 's/要被取代的字符串/新的字符串/g'
[wendy@cs011 develop]$ sbin/ifconfig eth0 | grep 'inet addr' | sed 's/^.*addr://g' |sed 's/Bcast.*$//g'
7.3 awk工具
awk:数据处理工具,相较于sed常常作用于一整个行的处理,awk则比较倾向于一行当中分成数个[字段]来处理,即awk不是[以行为一次处理的单位],而[以字段为最小的处理的单位]。
awk处理流程如下:
1.读入第一行,并将第一行的资料填入$0,$1,$2...等变数当中。$0表示一整行的内容,$1表示第一个参数
2.依据 条件类型 的限制,判断是否需要进行后面的动作
3. 做完所有的动作与条件类型
4. 若还有后续的行数据,则重复1-3的步骤,直到所有的数据都读完为止
//awk '条件类型1{动作1} 条件类型2{动作2}....' filename 。
awk主要处理每一行的字段内的数据,而默认的字段的分隔符为空格键或tab键。
//取出前5行,取出第一个参数和第三个参数,tab键隔开,用print的功能将字段数据列出来
last -n 5 | awk '{print $1 'tab' $3}'
//取出前5行,列出每一行的账号($1);列出目前处理的行数(NR变量);该行有多少字段(NF变量)
last -n 5 | awk '{print $1 "\tlines:"NR "\t columes:"NF}'
eg3://逻辑判断,BEGIN关键字
///etc/profile当中以冒号来作为字段的分隔,第一个字段是账号,第三个字段是UID
//需求:查询第三个参数小于10以下的数据,并且仅列出账号与第三栏
cat /etc/profile | awk 'BEGIN {FS=":"} $3<10 {print $1 "\t" $3}'
awk的逻辑运算字符:
7.4 printf打印
文件进行一些简单的编排,通过数据流重导向配合底下介绍的printf功能,以及awk指令。
//格式化打印:printf '打印格式' 实际内容
\a 警告声音输出
\b 退格键(backspace)
\f 清除屏幕(form feed)
\n 输出新的一行
\r Enter按键
\t 水平的tab按键
\v 垂直的tab按键
\xNN NN为两位数的数字,可以转换数字成为字符。
//关于C程序语言内,常见的变数格式
%ns:n=number;s=string,指的是多少个字符
%ni:n=number;i=integer,指的是多少整数字数
%N.nf:n、N=number;f=floating(浮点),如果有小数字数,比如%10.2f表示10个位数,但小数点有2位
正规表示法就是处理字符串的方法,以行为单位来进行字符串的处理行为。
正规表示法透过一些特殊字符的辅助,能达到搜索、删除、取代某特定字符串的处理程序。
只要工具程序支持正规表示法,该工具程序就可以用来作为正规表示法的字符串处理之用。
通配符代表的是bash操作接口的一个功能,但正规表示法则是一种字符串处理的表示方式。
使用grep或其他工具进行字符串比对,编码问题会有不同的状态。
基础正规表示法的特殊字符有:*、?、[]、[-]、[^]、^、$。
常见的正规表示法工具:grep、sed、vim。
printf可以透过一些特殊符号来讲数据进行格式化输出。
awk可以使用字段为依据,进行数据的重新整理与输出。
文件的比对中,可利用diff及cmp进行比对,其中diff及cmp进行比对,其中diff主要用在纯文本文件方面的新旧版本比对。
patch指令可以将旧版数据更新到新版。
8 shell script
8.1 为什么学习shell script
shell script 是利用shell的功能所写的一个程序,这个程序是使用纯文本文件,将一些shell的语法与指令(含外部指令)写在里面,搭配正规表示法、管线命令与数据流重导向等功能。
shell:文字接口底下让我们与系统沟通的一个工具接口。
shell script的特点:
自动化管理的重要性
追踪与管理系统的重要工作
简单入侵检测功能
连续指令单一化
简易的数据处理
跨平台支持与学习历程较短
shell script的注意事项:
1.指令的执行时从上而下、从左而右的分析与执行。
2.指令、选项与参数间的多个空白都会被忽略掉。
3.空白行也将被忽略掉,并且tab按键所推开的空白同样视为空格键。
4.如果读取到一个enter符号(CR),就尝试开始执行该行命令。
5.至于如果一行的内容太多,则可以使用[\enter]来延伸至下一行。
shell script的执行:
1.直接指令下达:shell.sh档案必须要具备可读与可执行(rx)的权限,然后:
绝对路径:使用/home/dmtsai/shell.sh来下达指令
相对路径:假设工作目录在/home/dmtsai/,则使用./shell.sh来执行
变量[PATH]功能:将shell.sh放在PATH指定的目录内,例如:~/bin/
2.以bash程序来执行:透过[bash shell.sh]或[sh shell.sh]来执行
PS:script的执行方式差异(source、sh script、./script)
1.利用直接执行的方式来执行script:比如sh sh02.sh
2.利用source来执行的脚本:在父程序中执行:source sh02.sh
//sh01.sh脚本内容如下:
#!/bin/bash
#program:
# This program shows "Hello World!" in your screen.
#History:
#2020/04/27 wendy First release
echo -e "Hello World!\a\n" // -e开启转义
exit 0
//执行方式一,先赋予权限,在执行
[wendy@cs011 scripts]$ chmod a+x sh01.sh
[wendy@cs011 scripts]$ ./sh01.sh
Hello World!
//执行方式二, /bin/sh 是/bin/bash(连结档),使用sh shell.sh告诉系统,直接bash的功能来执行shell.sh文件内的相关指令。
[wendy@cs011 scripts]$ sh sh01.sh
Hello World!
[wendy@cs011 scripts]$ bash sh01.sh
Hello World!
8.2 善用判断式:$?、&&、||
利用test指令的测试功能
//检测系统上面某些档案或相关的属性时
//比如:检查/dmtsai是否存在,同时透过$? 或&& 及||来展现整个结果。
[wendy@cs011 scripts]$ test -e /dmtsai && echo "exits" || echo "not exist"
not exist
[root@www scripts]# vi sh05.sh
#!/bin/bash
# Program:
# User input a filename, program will check the flowing:
# 1.) exist? 2.) file/directory? 3.) file permissions
# History:
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1. 输入文件名,并且判断是否真的有输入字符串?
echo -e "Please input a filename, I will check the filename's type and \
permission. \n\n"
read -p "Input a filename : " filename
test -z $filename && echo "You MUST input a filename." && exit 0
# 2. 判断文件是否存在?若不存在则显示信息并结束脚本
test ! -e $filename && echo "The filename '$filename' DO NOT exist" &&
exit 0
# 3. 开始判断文件类型与属性
test -f $filename && filetype="regulare file"
test -d $filename && filetype="directory"
test -r $filename && perm="readable"
test -w $filename && perm="$perm writable"
test -x $filename && perm="$perm executable"
# 4. 开始输出信息!
echo "The filename: $filename is a $filetype"
echo "And the permissions are : $perm"
利用判断符号[],注意事项:
在中括号[]内的每个组件都需要有空格键来分隔。
在中括号内的变数,最好都以双引号括号起来。
在中括号内的常数,最好都以单引号或双引号括号起来。
//判断$HOME这个变量是否为空
[ -z "$HOME" ];echo $?
//都有空格键,判断2个值是否相等(逻辑判断)
[ "$HOME" == "$MAIL" ] 类似于 test $HOME = $MAIL
shell script的默认变数($0,$1,$2...):
$#:代表后接的参数[个数]
$@:代表[ "$1" "$2" "$3" "$4" ],每个变量都是独立的(用双引号括起来)
$*:代表["$1c$2c$3c$4"],其中c为分隔字符,默认为空格键,所以本例中代表[ "$1" "$2" "$3" "$4" ]之意。
8.3 shell 的基础操作
对谈式脚本
随日期变化
对谈式脚本:变量内容由用户决定.
//read命令用于从标准输入读取数值(单行数据读取)。
-a:变量[数组],然后给其赋值,默认是以空格为分隔符。
-d:后面跟一个标识符,其实只有其后的第一个字符有用,作为结束的标志
-p:后面跟提示信息
-e:在输入的时候可以使用命令补全功能
-n:数字
//sh02.sh的脚本内容如下
#!/bin/bash
#program:
# User inputs his first name and last name.Program shows his full name.
#History:
#2020/4/27 wendy first release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "please input your first name:" firstname
read -p "please input your last name:" lastname
echo -e "\n your full name is :$firstname $lastname"
//执行命令,显示结果
[wendy@cs011 scripts]$ sh sh02.sh
please input your first name:wendy //输入wendy
please input your last name:we //输入we
your full name is :wendy we //显示wendy we
sh02.sh在子程序中运作:
随日期变化:利用date进行文件的建立
//sh03.sh文件内容
#!/bin/bash
#program:
# program creates three files,which named by user's input and date command
#History:
#2020/4/27 wendy first release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "I will use touch command to create 3 files"
read -p "please input your filename:" fileuser
filename=${fileuser:-"filename"}
date1=$(date --date='2 days ago' +%Y%m%d)# 前两天的日期
date2=$(date --date='1 days ago' +%Y%m%d)# 前一天的日期
date3=$(date +%Y%m%d)
file1=${filename}${date1}
file2=${filename}${date2}
file3=${filename}${date3}
touch "$file1"
touch "$file2"
touch "$file3"
//命令执行结果
[wendy@cs011 scripts]$ sh sh03.sh
I will use touch command to create 3 files
please input your filename:we
[wendy@cs011 scripts]$ ll
-rw-rw-r-- 1 wendy wendy 744 Apr 28 12:47 sh03.sh
-rw-rw-r-- 1 wendy wendy 0 Apr 28 12:47 we20200426
-rw-rw-r-- 1 wendy wendy 0 Apr 28 12:47 we20200427
-rw-rw-r-- 1 wendy wendy 0 Apr 28 12:47 we20200428
数值运算 :var=$((运算内容)) 或declare -i total=$firstnu*$secnu
//sh04.sh的内容
#!/bin/bash
#program:
# user inputs 2 integer numbers;program will cross these two numbers.
#History:
#2020/4/27 wendy first release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "you should input 2 number,I will cross them!\n"
read -p "first number:" firstnu
read -p "second number:" secnu
total=$(($firstnu*$secnu))
echo -e "\nThe result of $firstnu x $secnu is ==$total"
//执行结果
[wendy@cs011 scripts]$ sh sh04.sh
you should input 2 number,I will cross them!
first number:4
second number:4
The result of 4 x 4 is ==16
8.4 条件判断式
利用if...then:单层简单条件,多重复杂条件,检验$1内容,网络状态,退伍
利用case...esac判断
利用function功能
单重条件判断式:
//条件判断式中的内容可以通过 && 或 || 隔开。
if [ 条件判断式 ];
then 当条件判断式成立时,可以进行的指令工作内容
//条件判断式内容
[ "$yn" == "Y" -o "$yn" == "y" ]
类似于[ "$yn" == "Y" ] || [ "$yn" == "y" ]
if [ "$yn" == "Y" ] || [ "$yn" == "y" ] ;then
echo "ok,contine"
exit 0
多重、复杂条件判断式:
//一个条件判断,分成功进行与失败进行(else)
if [ 条件判断式 ];then
当条件判断式成立时,可以进行的指令工作内容;
当条件判断式不成立时,可以进行的指令工作内容
//多个条件判断(if...elif...elif...else)分多种不同情况执行
if [ 条件判断式一 ];then
当条件判断式成立时,可以进行的指令工作内容;
elif [ 条件判断式二 ];then
当条件判断式不成立时,可以进行的指令工作内容
当条件判断式一或二都不成立时,可以进行的指令工作内容
if [ "$yn" == "y" ] || [ "$yn" == "Y" ];then
echo "ok,continue"
echo "no ok!"
if [ "$yn" == "y" ] || [ "$yn" == "Y" ];then
echo "ok,continue"
elif [ "$yn" == "n" ] || [ "$yn" == "N" ];then
echo "no ok!"
echo "I don't know!"
case...in...esac判断
ps:[ case $变量 in ]中[$变量]有两种取得的方式:直接下达式和交互式。
直接下达式:[ script.sh variable ]的方式来直接给予$1这个变量的内容
交互式:透过read这个指令来让用户输入变量的内容
//case...in...esac判断
case $变量名称 in
"第一个变量内容")
"第二个变量内容")
//需求:使用者能够输入one,two,并且将用户的变量显示在屏幕上
eg1:sh12.sh内容如下
#read -p "please your choice:"$choice
#case $choice in //交互式
case $1 in //下达式
"one")
echo "is one"
"two")
echo "is two"
echo "usage $0 {one|two}"
esac
//下达式命令执行:sh sh12.sh two
//显示结果:is two
function()功能
//frame是自定义的执行指令名称,且function一般要放在设定程序的最前面。
function fname(){
8.5 循环(loop)
while...do...done,util...do...done(不定循环)
for...do...done(固定循环):账号检查,网络状态$(seq)
for...do...done的数值处理
while...do...done,util...do...done(不定循环):
//while...do...done,中括号内的状态condition就是判断式
//当condition条件成立时,就进行循环,直到condition的条件不成立才停止
while [ condition ]
//until...do...done(不定循环)
//当condition条件成立时,就终止循环,否则就持续进行循环的程序段
until[ condition ]
//求1+2+...+100的和
s=0
i=0
while [ "$i" != "100" ]
i=$(($i+1))
s=$(($s+$i))
echo "the result of '1+2+3+...+100'is ==>$s"
for...do...done(固定循环):账号检查,网络状态$(seq)
//for...do...done(固定循环):账号检查,网络状态$(seq)
for var in con1 con2 con3...
for animal in dog cat elephant
echo "there are ${animal}s..."
for...do...done的数值处理
//初始值:某个变量在循环当中的起始值
for(( 初始值;限制值;执行步阶 ))
shell script 是利用shell的功能所写的一个程序,这个程序是使用纯文本文件,将一些shell的语法与指令(含外部指令)写在里面,搭配正规表示法、管线命令与数据流重导向等功能。
shell script执行顺序:从上而下、从左而右的分析与执行
shell script的执行,至少需要有r的权限,若需要直接指令下达,则需要拥有r与x的权限
script 的执行以source来执行时,代表在父程序的bash内执行之意
若需要进行判断式,可使用test或中括号[]来处理
使用sh -x script.sh来进行程序的debug
9 shell 简单操作
9.1 变量
语法:变量名=变量值
PS:=两边不能有空格
1、使用变量:$变量名
ex: Name="wendy"#声明变量
echo $Name 或 echo ${Name} #输出变量
ps:花括号可选
2、只读变量:readonly 变量
3、删除变量:unset 变量
4、字符串变量长度获取:${#字符串变量}
ps: string="abcd" echo ${#string} #输出4
5、字符串变量提取部分:${变量:1:4} #表示从第二个字符开始,截取4个字符
ex:string="abcdedfg" echo ${变量:1:4} #输出bcde
在bash中,每一个变量的值都是字符串。
9.2 变量类型
局部变量:只对当前shell有效
环境变量:所有程序都能访问环境变量
shell变量:可设置
9.3 符号问题
单引号:变量无效,任何字符原样输出
双引号:可使用变量,可以出现转义字符
ps:拼接字符串用双引号,且变量需要用{}
注释问题:
单行注释:#
多行注释: :<<EOF 注释内容 EOF(EOF可以替换为其他任意字符)
9.4 数组
定义数组:数据名=(值1 值2 值3...值n)或数组名=(
value0
value1
value2
value3
)或 数据名[0]=value0 数据名[1]=value1
ex:array_name=(value0 value1 value2)
读取数组:${数组名[下标]}
ex:value=${数组名[n]} #@表示获取数组中的单个元素
length=${#数组名[@ || *]}# @、*表示获取数组所有元素的长度
9.5 参数处理
$# 脚本后面接的参数的个数
$* 脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
$@ 脚本后面所有参数,参数是独立的,也是全部输出
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$? 上一条命令执行后返回的状态,0表示没有错误,0以外其他所有值表示有错误
9.6 运算符:
算数运算符: + - * / % = == !=
关系运算符:-eq -ne -gt -ge -lt -le(= != > >= < <=)
布尔运算符:! -o -a(or and)
逻辑运算符: && ||
字符串运算符:= != -z -n $(= != 判断=0为真 判断!=0为真 判断是空为真)
文件测试运算符:(-e -r -w -x -s -d -f -c -b)+文件名 文件存在且可读、可写、可执行、至少有一个字符、是目录、普通文件、字符型特殊文件、块特殊文件
9.7 shell函数:
[ function ] funname [()]
action;
[return int;]
或者function fun()
或者fun()
ps:参数返回,可以显示加;
9.8 shell 输入/输出重定向:
command > file 将输出重定向到file
command < file 将输入重定向到file
command >> file 将输出以追加的方式重定向到file
n >& m 将输出文件m和n合并
n <& m 将输入文件m和n合并
<<tag 将开始标记tag和结束tag之间的内容作为输入
/dev/null:不希望在屏幕上显示输出结果 ,重定向到垃圾箱/dev/null