shell 编程 && bash 简介(shell 变量、shell操作环境、数据流重导向、管线命令、shell script)

如何学习一门编程语言 

  1. 数据类型

  2. 运算符

  3. 关键字

1 认识BASH 这个shell

linux是操作系统核心,用户通过shell与核心进行沟通,达到我们想要的目的。硬件、核心、用户之间的关系:

原理:所谓Shell程序,实际上是提供用户操作系统的一个接口,用户可以通过shell程序操作其他应用程序(eg. ls,chown,etc.),让这些应用程序可以呼叫内核来完成工作。Bash是Linux系统下的其中一种Shell程序。当前系统支持哪些Shell程序,可查看/etc/shells配置文件;查看用户配置使用的哪种shell,可查看/etc/passwd配置文件。

bash:The Bourne Again Shell。

shell:接口程序,是一个命令语言解释器,拥有内建的命令集。

1.1 为何要学文字接口的shell

  1. Shell操作方式一致,可一法通、万法通;
  2. 远程管理;
  3. 主机管理及shell编程;

1.2 bash shell的功能

//历史查看,在[~/.bash_history]中记录前一次登入以前所执行过的指令,本次执行会暂存在内存中,成功注销后,才会记录到bash_history当中。
history

//命令补全功能:tab
tab

//命令别名,自定义设定别名,比如alias lm='ls -al'
alias lm='ls -al'

//通配符*
ls -l /user/bin/X*  //查看在/usr/bin底下有多少以X为开头的文件

1.3 bash shell的内建命令:type

//type内建命令,type [-tpa] name,选项与参数
 -t:file表示为外部指令;alias 表示命令别名所设定的名称;builtin 表示bash内建的命令
 -p:name为外部指令,才会显示完整文件名
 -a:PATH变量定义路径中,将所有含name指令都列出来,包含alias
eg:
//查看一下pwd这个指令是否为bash内建,列出主要使用情况
[wendy@cs011 ~]$ type pwd  //内建命令
pwd is a shell builtin
[wendy@cs011 ~]$ type -a pwd
pwd is a shell builtin
pwd is /usr/bin/pwd
[wendy@cs011 ~]$ type -t pwd  //内建命令,列出执行时的情况
builtin
[wendy@cs011 ~]$ type ls
ls is aliased to `ls --color=auto`
[wendy@cs011 ~]$ type -a ls
ls is aliased to `ls --color=auto`  //先使用alias
ls is /usr/bin/ls                         //找到外部命令在bin/ls
[wendy@cs011 ~]$ type -t ls  //别名,列出执行时的情况
alias

2 shell的变量功能

变量:让某一个特定字符串代表不固定的内容。即变量就是以一组文字或符号等,来取代一些设定或者一串保留的数据。比如y=ax+b,y就是变量,ax+b是变量的内容。

取用变量:echo $变量名,比如:echo $PATH 或 echo ${PATH}

变量的有效范围:比如export后的变量,称为环境变量。环境变量可以被子程序所引用,但其他的自定义变量就不会存在于子程序中。全局变量 = 环境变量;自定义变数 = 局部变量

  • 当启动一个shell,操作系统会分配一记忆区块给shell使用,内存内的变量可以让子程序取用。
  • 父程序利用export功能,可以让自定义变量的内容写入到记忆区块中。
  • 当加载另一个shell时,子shell可以将父shell的环境变量所在的记忆区块导入自己的环境变量区块中。

Bash的变量分为2种:环境变量(可分为系统级别或用户级别)、普通变量。
普通变量即用户自定义的变量,变量的设定规则如下:

  • 1.变量与变量内容以一个等号=来连接,比如[ myname=VBird ]
  • 2.等号两边不能有空格;
  • 3.变量名称只能是英文字母与数字,且必须以英文字母开头;
  • 4.变量获取使用,可以通过$var或者${var}读取2种写法;
  • 5.变量内容若有空格符,可使用单引号或者双引号将变量内容结合在一起;

A.单/双引号的区别在于:双引号内的特殊字符如$, 反引号等,可以保留原本特性;而单引号内的特殊字符则仅作为一般字符(纯文本);

//双引号内的特殊字符如$等,可以保有原本的属性
[wendy@cs011 ~]$ var="lang is $LANG"
[wendy@cs011 ~]$ echo $var
lang is en_US.UTF-8
[wendy@cs011 ~]$ var='lang is $LANG'
[wendy@cs011 ~]$ echo $var
lang is $LANG

B.单/双引号使用规则是:

      • 1)双引号之间可有成对双引号,也可有成对单引号,当内外均是双引号时,内部双引号之间不能有空格 ;
      • 2)单引号之间可有成对双引号,也可有成对单引号,当内外均是单引号时,内部单引号之间不能有空格;
      • 3)双引号内可有单个单引号不能有单个双引号,除非以转移字符转义内部双引号;
      • 4)单引号内可有单个双引号,不能有单个单引号,即使转义内部单引号也不行;
  • 6.可以用转义字符\将特殊符号如ENTER, $, \, 空格等变成一般字符;
  • 7.如果在一串指令中,还需要其他指令提供的信息,可以使用反单引号【ESC键正下方】或者$()来实现;
[wendy@cs011 ~]$ v=$(uname -r)
[wendy@cs011 ~]$ echo $v
3.10.0-862.2.3.el7.x86_64
[wendy@cs011 ~]$ v1=`uname -r` //``这个是tab键上面的那个顿点
[wendy@cs011 ~]$ echo $v1
3.10.0-862.2.3.el7.x86_64
  • 8.如果变量需要在其他子程序中使用,可以用export命令将其变成环境变量;
//该变量在其他子程序执行,需要用export来使变量变成环境变量
export PATH

//变量为扩增变量,可用"$变量名称" 或${变量}累加内容
[wendy@cs011 develop]$ version=1
[wendy@cs011 develop]$ echo $version
1
[wendy@cs011 develop]$ version="$version":/第二个参数
[wendy@cs011 develop]$ echo $version
1:/第二个参数
[wendy@cs011 develop]$ version=$version:/第三个参数
[wendy@cs011 develop]$ echo $version
1:/第二个参数:/第三个参数
[wendy@cs011 develop]$ version=$version:/第四个参数
[wendy@cs011 develop]$ echo $version
1:/第二个参数:/第三个参数:/第四个参数
  • 9.取消自定义变量命令unset;
  • 10.交互获取变量命令read;
  • 11.关于bash的补充说明:环境变量可理解为bash的全局变量,在用户取得bash时初始化并赋值。环境变量的初始化配置文件及读取顺序如下:

a.变量类型默认为“字符串”,可用declare申明变量类型

b.bash环境中的数值运算,预设的精度仅能达到整数形态;

  • 12.环境变量查看命令env;环境变量及自定义变量查看命令set。
//列出目前的shell环境下的所有环境变量与其内容
env
//set观察所有变量(含环境变量与自定义变量)
set
ps:env 与set 区别:该变量是否会被子程序所继续引用
//export:自定义变量转成环境变量,可以使用declare
export  //显示所有的环境变量

2.1 影响显示结果的语系变量(locale)

//locale -a :后面可以不加任何选项与参数
[wendy@cs011 ~]$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"

2.2 变量键盘读取、数组与宣告:read,array,declare

//read :读取来自键盘输入的变量。read [-pt] variable
 -p:后面可以接提示字符
 -t:后面可以接等待的秒数
eg:
[wendy@cs011 ~]$ read atest
aaaa    //等待输入,键盘输入内容
[wendy@cs011 ~]$ echo $atest
aaaa

[wendy@cs011 ~]$ read -p atest:
atest:wendy
[wendy@cs011 ~]$ echo $atest
aaaa

//declare/typeset:宣告变量的类型,declare [-aixr] variable
 -a:变量定义成为数组类型(array)
 -i:变量成为整数数字类型(integer)
 -x:export一样,变成为环境变量
 -r:变量设定为readonly类型,该变量不能更改,也不能unset。需要注销在登入才能复原该变量类型

eg:
[wendy@cs011 ~]$ declare -i sum=10+20   //-i 定义变量sum为integer
[wendy@cs011 ~]$ echo $sum
30

[wendy@cs011 ~]$ declare -x sum   //-x 定义变量sum为环境变量
[wendy@cs011 ~]$ export | grep sum
declare -ix sum="30"

[wendy@cs011 ~]$ declare -r sum  //-r 定义变量sum为只读
[wendy@cs011 ~]$ sum=10+20+30
-bash: sum: readonly variable

//让sum变成非环境变量的自定义变量
[wendy@cs011 ~]$ declare +x sum  //+x 取消变量为自定义变量
[wendy@cs011 ~]$ declare -p sum
declare -ir sum="30"
//数组变量类型
[wendy@cs011 ~]$ var[1]="small min"
[wendy@cs011 ~]$ var[2]="big min"
[wendy@cs011 ~]$ var[3]="nice min"
[wendy@cs011 ~]$ echo "${var[1]},${var[2]},${var[3]}"
small min,big min,nice min

 

3 命令别名与历史命令

//命令别名设定:alias, 别名='指令 选项....'
alias lm='ls -al | more'

//取消命令别名unalias
unalias lm

//history[n][-c]   或history [-raw] hisfiles
 n:数字
 -c:将目前的shell中的所有history内容全部消除
 -a:目前新增的history指令新增入histfiles,若没有加hisfiles,则预设写入~/.bash_history
 -r:将histfiles的内容读到目前这个shell的history记忆
 -w:将目前的history记忆内容写入histfiles中

eg:
[wendy@cs011 ~]$ history 3
  999  alias
 1000  clear
 1001  history 3
[wendy@cs011 ~]$ history -w
[wendy@cs011 ~]$ echo $HISTSIZE
1000
[wendy@cs011 ~]$ history 3
 1002  history -w
 1003  echo $HISTSIZE
 1004  history 3

4 bash shell 的操作环境

4.1 路径与指令搜索顺序

  • 1.以相对/绝对路径执行指令,例如[/bin/ls]或[./ls]
  • 2.由alias找到该指令来执行
  • 3.由bash内建的builtin指令来执行
  • 4.透过$PATH这个变量的顺序搜寻到的第一个指令来执行
//指令执行顺序
[wendy@cs011 ~]$ alias echo='echo -n'
[wendy@cs011 ~]$ type -a echo
echo is aliased to `echo -n`
echo is a shell builtin
echo is /usr/bin/echo

4.2 bash的进站与欢迎讯息

// bash进站与欢迎讯息:/etc/issue、/etc/motd
[wendy@cs011 ~]$ cat /etc/issue
\S
Kernel \r on an \m 

4.3 环境配置文件

环境配置文件:login、non-login shell、/etc/profile、~/.bash_profile,source,~/.bashrc

//bash的环境配置文件:login、non-login shell、/etc/profile、~/.bash_profile,source,~/.bashrc
//login shell读取的配置文件
1、/etc/profile:login shell才会读,这是系统整体的设定,最好不要修改这个档案
2、~/.bash_profile或~/.bash_login或~/.profile:属于使用者个人设定,你要改自己的数据,依次执行

login shell的配置文件读取流程:实现的方向是主线流程 ,虚线的方向则是被呼叫的配置文件。在centos的login shell环境下,最终被读取的配置文件是[~/.bashrc]这个文件。

//source:读入环境配置文件的指令,/etc/profile与~/.bash_profile都是在取得login shell的时候才会读取的配置文件。
//source 配置文件档名,利用source或小数点(.)都可以将配置文件的内容读进来目前的shell环境中。

eg://将home目录的~/.bashrc的设定读入目前的bash环境中,有如下2种方式。
[wendy@cs011 ~]$ source ~/.bashrc
[wendy@cs011 ~]$ . ~/.bashrc
//non-login shell情况下,bash配置文件仅会读~/.bashrc
[wendy@cs011 ~]$ cat ~/.bashrc
# .bashrc
# Source global definitions //整体的环境设定
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

 4.4 终端机的环境设定

//终端机的环境设定:stty,set 。可以在tty1~tty6这六个文字接口的终端机环境中登入。syyt [-a]
 -a :将目前所有的stty参数列出来

eg:
[wendy@cs011 ~]$ stty -a
speed 38400 baud; rows 43; columns 115; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

//set [-uvCHhmBx]
 -u:默认不启用,启用时,未设定变量时,会显示错误信息
 -v:默认不启用,启用后,讯息被输出前,会先显示讯息的原始内容
 -x:默认不启用,启用后,在指令被执行前,会显示指令内容
 -h:默认启用,与历史命令有关
 -H:默认启用,与历史命令有关
 -m:默认启用,与工作管理有关
 -B:默认启用,与刮号[]的作用有关
 -C:默认不启用,若使用>等,则若文件存在时,该文件不会被覆盖

//$- :变量内容就是set的所有设定,bash预设是himBH
[wendy@cs011 ~]$ echo $-
himBH

[wendy@cs011 ~]$ set -u
[wendy@cs011 ~]$ echo $vbirding
-bash: vbirding: unbound variable

[wendy@cs011 ~]$ set -x
++ printf '\033]0;%s@%s:%s\007' wendy cs011 '~'

[wendy@cs011 ~]$ echo $HOME
+ echo /home/wendy 
/home/wendy 
++ printf '\033]0;%s@%s:%s\007' wendy cs011 '~' 

常用的快捷键:

Ctr + C

终止当前任务

Ctr + Z

暂停当前任务

Ctr + S

暂停屏幕输出

Ctr + Q

回复屏幕输出

Ctr + U

删除提示符之前内容

Ctr + K

删除提示符之后内容

4.5 通配符与特殊符号

特殊符号:

通配符:

eg:
//找出/etc/底下文件名刚好是5个字母的文件名
[wendy@cs011 ~]$ ll -d /etc/?????
drwxr-x---. 3 root root 4096 Mar 20  2019 /etc/audit

//找出/etc/底下以cron为开头的文件名
[wendy@cs011 ~]$ ll -d /etc/cron*
drwxr-xr-x. 2 root root 4096 Mar 20  2019 /etc/cron.daily

//找出/etc/底下文件名含有数字的文件名
[wendy@cs011 ~]$ ll -d /etc/*[0-9]*
-rw-r--r--  1 root root  228 Oct 18  2017 /etc/m2.conf

//找出/etc/底下文件名开头不为大写字母开头的文件名
[wendy@cs011 ~]$ ll -d /etc/[^A-Z]*
-rwxrwxrwx  1 root root 1789280 Mar 20  2019 /etc/aayx

5 数据流重导向(Redirection)

数据流重导向:将某个指令执行后出现在屏幕上的数据。

  • 标准输出:指的是指令执行所回传的正确的讯息。
  • 标准错误输出:指令执行失败后,所回传的错误讯息。

指令执行过程的数据传输情况示意图:

数据流重导向可以将standard output(简称stdout)与standard error output(简称stderr)分别传送所用的特殊字符如下:

  • 1.标准输入(stdin):代码为0,使用< 或 << ;
  • 2.标准输出(stdout):代码为1,使用> 或>>;
  • 3.标准错误输出(stderr):代码为2,使用2> 或2>>;
  • 4./dev/null:垃圾桶黑洞装置与特殊写法
//用cat直接将输入的讯息输出到catfile中,且当由键盘输入eof时,该次输入就结束
cat > catfile << "eof"

eg:
[wendy@cs011 develop]$ cat >test.txt <<"eof"
> wendy001
> wendy002
> wendy003
> eof   //输入这关键字,立刻就结束而不需要输入ctrl+d
[wendy@cs011 develop]$ vi test.txt
[wendy@cs011 develop]$ cat >test.txt <<"eof"
> wendy004
> wendy005
> wendy006
> eof
[wendy@cs011 develop]$ vi test.txt
[wendy@cs011 develop]$ cat >>test.txt <<"eof"
> wendy001
> wendy002
> wendy003
> eof

命令执行的判断依据:;.&& ||

//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 字符区间

eg:
[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:可以将找到的关键词部分加上颜色的显示.
eg:
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)来进行排序
eg:
//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
1
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:取代掉重复的字符

eg:
//将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:代表前导符的意思,可作为分割文件的前导文字。

eg:
//分割命令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时,都会询问使用者的意思

eg:
[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 可将正确的那个截取数据列出颜色

eg1:
//用dmesg列出核心信息,再以grep 找到eth所在行的前2行与后三行也一起进行显示
dmesg | grep -n -A3 -B2 --color=auto 'eth'

eg2:
test.txt文件内容:001:wendy:004002:wendy:005003:wendy:006004:wendy:001005:wendy:002006: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

 显示结果如图

eg2://反向选择,从test.txt中搜索不包含001的行

[wendy@cs011 develop]$ grep '[^001]' test.txt 

  显示结果如图:

//3.利用中括号[]来搜寻集合字符,比如搜索0*:wendy或0*:wendy,*表示随意 //[]里面无论有几个字符,都只代表一个字符

[haishu@cs011 develop]$ grep -n '0[0-9]:wendy' test.txt

  显示结果如图:

//4.在g与g之间有2个到3个的o存在的字符串。\{n,m\}:指的是连续n到m个以上的前一个Re字符。

[haishu@cs011 develop]$ grep -n 'go\{2,3\}g' regular_express.txt

正规表示法与通配符完全不一样,通配符代表的是bash操作接口的一个功能,但正规表示法则是一种字符串处理的表示方式。

使用grep或其他工具进行正规表示法的字符串比对时,编码问题会有不同的状态,设置LANG等变量设定为C或是en的英文语系,可利用特殊符号[:upper:]来替代编码范围。

grep与egrep在正规表示法里面常见的两支程序,其中egrep更支持正规表示法的语法。

grep -v '^$' test.txt | grep -v '^#' //egrep进行简化,透过群组功能|来进行一次搜寻。grep -E = egrep 的写法

egrep -v '^$ | ^#' test.txt

基础的正规表示法[grep]:

 

延伸的正规表示法[egrep]

 

7.2 sed 工具

sed是一个管线命令,可以分析stdin等。

sed功能:数据进行取代、删除、新增、截取特定行等等的功能。 

// 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:插入,接字符串,新行出现
d:删除
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键。
eg1:
//取出前5行,取出第一个参数和第三个参数,tab键隔开,用print的功能将字段数据列出来
last -n 5 | awk '{print $1 'tab' $3}'
eg2:
//取出前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是否存在,同时透过$? 或&& 及||来展现整个结果。
eg:
[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:数字
 
eg:
//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 当条件判断式成立时,可以进行的指令工作内容
fi

//条件判断式内容
[ "$yn" == "Y" -o  "$yn" == "y" ] 
类似于[ "$yn" == "Y" ] || [ "$yn" == "y" ] 

eg:
if [ "$yn" == "Y" ] || [ "$yn" == "y" ] ;then
    echo "ok,contine"
    exit 0
fi

多重、复杂条件判断式:

//一个条件判断,分成功进行与失败进行(else)
if [ 条件判断式 ];then
    当条件判断式成立时,可以进行的指令工作内容;
else
    当条件判断式不成立时,可以进行的指令工作内容
fi

//多个条件判断(if...elif...elif...else)分多种不同情况执行
if [ 条件判断式一 ];then
    当条件判断式成立时,可以进行的指令工作内容;
elif [ 条件判断式二 ];then
    当条件判断式不成立时,可以进行的指令工作内容
else
    当条件判断式一或二都不成立时,可以进行的指令工作内容
fi

eg1:
if [ "$yn" == "y" ] || [ "$yn" == "Y" ];then
    echo "ok,continue"
else
    echo "no ok!"
fi

eg2:
if [ "$yn" == "y" ] || [ "$yn" == "Y" ];then
    echo "ok,continue"
elif [ "$yn" == "n" ] || [ "$yn" == "N" ];then
    echo "no ok!"
else
    echo "I don't know!"
fi     

case...in...esac判断

ps:[ case $变量 in ]中[$变量]有两种取得的方式:直接下达式和交互式。

  • 直接下达式:[ script.sh variable ]的方式来直接给予$1这个变量的内容
  • 交互式:透过read这个指令来让用户输入变量的内容
//case...in...esac判断
case $变量名称 in 
    "第一个变量内容")
        程序段
    ;;
    "')
    "第二个变量内容")
        程序段
    ;; 
    *)
        程序段
    ;;
esac
//需求:使用者能够输入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 ] 
do
    程序段落
done

//until...do...done(不定循环)
//当condition条件成立时,就终止循环,否则就持续进行循环的程序段
until[ condition ] 
do
    程序段落
done
//求1+2+...+100的和
eg1:
s=0
i=0
while [ "$i" != "100" ] 
do
    i=$(($i+1))
    s=$(($s+$i))
done
echo "the result of '1+2+3+...+100'is ==>$s" 

for...do...done(固定循环):账号检查,网络状态$(seq)

//for...do...done(固定循环):账号检查,网络状态$(seq)
for var in con1 con2 con3...
do
    程序段
done
eg1:
for animal in dog cat elephant
do
    echo "there are ${animal}s..."
done

for...do...done的数值处理

//初始值:某个变量在循环当中的起始值
for(( 初始值;限制值;执行步阶 ))
do
    程序段
done

重点:

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
posted @ 2019-09-27 16:46  wendyw  阅读(856)  评论(0编辑  收藏  举报