0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一文吃透shell编写工具及基本法则!

jf_TEuU2tls 来源:浩道linux 2023-02-14 18:11 次阅读

前言

大家好,这里是浩道linux,主要给大家分享linux、python网络通信相关的IT知识平台。

今天浩道跟大家分享关于shell编程相关的硬核干货,通过本文你将吃透shell编写相关工具及基本法则。让你编写shell脚本如鱼得水!

文章来源:资源整理综合自网络

1. 文件处理工具

1.1 grep工具

过滤

grep用于根据关键字进行行过滤
grepoptions'keys'filename
OPTIONS:
-i:不区分大小写
-v:查找不包含指定内容的行,反向选择
-w:按单词搜索
-o:打印匹配关键字
-c:统计匹配到的次数
-n:显示行号
-r:逐层遍历目录查找
-A:显示匹配行及后面多少行
-B:显示匹配行及前面多少行
-C:显示匹配行前后多少行
-l:只列出匹配的文件名
-L:列出不匹配的文件名
-e:使用正则匹配
-E:使用扩展正则匹配
^key:以关键字开头
key$:以关键字结尾
^$:匹配空行
--color=auto :可以将找到的关键词部分加上颜色的显示

临时设置:
#aliasgrep='grep--color=auto'//只针对当前终端和当前用户生效

永久设置:
1)全局(针对所有用户生效)
vim/etc/bashrc
aliasgrep='grep--color=auto'
source/etc/bashrc

2)局部(针对具体的某个用户)
vim~/.bashrc
aliasgrep='grep--color=auto'
source~/.bashrc

示例:
#grep-irootpasswd忽略大小写匹配包含root的行
#grep-wftppasswd精确匹配ftp单词
#grep-whellopasswd精确匹配hello单词;自己添加包含hello的行到文件中
#grep-woftppasswd打印匹配到的关键字ftp
#grep-nrootpasswd打印匹配到root关键字的行好
#grep-nirootpasswd忽略大小写匹配统计包含关键字root的行
#grep-nicrootpasswd忽略大小写匹配统计包含关键字root的行数
#grep-i^rootpasswd忽略大小写匹配以root开头的行
#grepbash$passwd匹配以bash结尾的行
#grep-n^$passwd匹配空行并打印行号
#grep^#/etc/vsftpd/vsftpd.conf匹配以#号开头的行
#grep-v^#/etc/vsftpd/vsftpd.conf匹配不以#号开头的行
#grep-A5mailpasswd匹配包含mail关键字及其后5行
#grep-B5mailpasswd匹配包含mail关键字及其前5行
#grep-C5mailpasswd匹配包含mail关键字及其前后5行

1.2 cut工具

截取

cut用于列截取
-c:以字符为单位进行分割。
-d:自定义分隔符,默认为制表符。	
-f:与-d一起使用,指定显示哪个区域。

#cut-d:-f11.txt以:冒号分割,截取第1列内容
#cut-d:-f1,6,71.txt以:冒号分割,截取第1,6,7列内容
#cut-c41.txt截取文件中每行第4个字符
#cut-c1-41.txt截取文件中每行的1-4个字符
#cut-c4-101.txt
#cut-c5-1.txt从第5个字符开始截取后面所有字符

课堂练习:
用小工具列出你当系统的运行级别。5/3

1.3 sort工具

排序

sort:将文件的每一行作为一个单位,从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

-u :去除重复行
-r :降序排列,默认是升序
-o:将排序结果输出到文件中类似重定向符号>
-n :以数字排序,默认是按字符排序
-t :分隔符
-k :第N列
-b :忽略前导空格。
-R :随机排序,每次运行的结果均不同。

示例:
#sort-n-t:-k31.txt按照用户的uid进行升序排列
#sort-nr-t:-k31.txt按照用户的uid进行降序排列
#sort-n2.txt按照数字排序
#sort-nu2.txt按照数字排序并且去重
#sort-nr2.txt
#sort-nru2.txt
#sort-nru2.txt
#sort-n2.txt-o3.txt按照数字排序并将结果重定向到文件
#sort-R2.txt
#sort-u2.txt

1.4 uniq工具

去除连续重复

uniq:去除连续重复行
-i:忽略大小写
-c:统计重复行次数
-d:只显示重复行

#uniq2.txt
#uniq-d2.txt
#uniq-dc2.txt

1.5 tee工具

tee工具从标准输入读取并写入标准输出和文件,即:双向覆盖重定向<屏幕输出|文本输入>
-a双向追加重定向

#echohelloworld
#echohelloworld|teefile1
#catfile1
#echo999|tee-afile1
#catfile1

1.6 paste工具

paste工具用于合并文件行

-d:自定义间隔符,默认是tab
-s:串行处理,非并行

[root@servershell01]#cata.txt
hello
[root@servershell01]#catb.txt
helloworld
888
999
[root@servershell01]#pastea.txtb.txt
hellohelloworld
888
999
[root@servershell01]#pasteb.txta.txt
helloworldhello
888
999

[root@servershell01]#paste-d'@'b.txta.txt
helloworld@hello
888@
999@

[root@servershell01]#paste-sb.txta.txt
helloworld888999
hello

1.7 tr工具

==字符转换:替换,删除==

tr用来从标准输入中通过替换或删除操作进行字符转换;主要用于删除文件中控制字符或进行字符转换。
使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。

语法:
commands|tr'string1''string2'
tr'string1''string2'< filename

tr options 'string1' < filename

-d 删除字符串1中所有输入字符。
-s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。


    a-z 任意小写
    A-Z 任意大写
    0-9 任意数字
  []       all letters and digits        所有字母和数字
  []       all letters                        所有字母
  []       all horizontal whitespace    所有水平空白
  []       all control characters        所有控制字符
 Ctrl-H          退格符
f Ctrl-L          走行换页

 Ctrl-J          新行

 Ctrl-M          回车
	 Ctrl-I          tab键
  []    all digits    所有数字
  []    all printable characters, not including space
  所有可打印的字符,不包含空格
  []       all lower case letters        所有小写字母
  []       all printable characters, including space
  所有可打印的字符,包含空格
  []       all punctuation characters            所有的标点符号
  []       all horizontal or vertical whitespace    所有水平或垂直的空格
  []       all upper case letters                所有大写字母
  []      all hexadecimal digits                所有十六进制数字
  [=CHAR=]        all characters which are equivalent to CHAR    所有字符



[root@server shell01]# cat 3.txt     自己创建该文件用于测试
ROOT0root:/root:/bin/bash
bin1bin:/bin:/sbin/nologin
daemon2daemon:/sbin:/sbin/nologin
adm3adm:/var/adm:/sbin/nologin
lp4lp:/var/spool/lpd:/sbin/nologin
sync5sync:/sbin:/bin/sync
shutdown6shutdown:/sbin:/sbin/shutdown
halt7halt:/sbin:/sbin/halt
mail8mail:/var/spool/mail:/sbin/nologin
uucp10uucp:/var/spool/uucp:/sbin/nologin
boss02516:/home/boss02:/bin/bash
vip517:/home/vip:/bin/bash
stu1518:/home/stu1:/bin/bash
mailnull47:/var/spool/mqueue:/sbin/nologin
smmsp51:/var/spool/mqueue:/sbin/nologin
aaaaaaaaaaaaaaaaaaaa
bbbbbb111111122222222222233333333cccccccc
hello world 888
666
777
999


# tr -d '[:/]' < 3.txt                 删除文件中的:和/
# cat 3.txt |tr -d '[:/]'            删除文件中的:和/
# tr '[0-9]' '@' < 3.txt             将文件中的数字替换为@符号
# tr '[a-z]' '[A-Z]' < 3.txt         将文件中的小写字母替换成大写字母
# tr -s '[a-z]' < 3.txt             匹配小写字母并将重复的压缩为一个
# tr -s '[a-z0-9]' < 3.txt         匹配小写字母和数字并将重复的压缩为一个
# tr -d '[]' < 3.txt         删除文件中的数字
# tr -d '[]' < 3.txt         删除水平空白
# tr -d '[]' < 3.txt         删除所有水平和垂直空白

小试牛刀

使用小工具分别截取当前主机IP;截取NETMASK;截取广播地址;截取MAC地址

[root@servershell01]#ifconfigeth0|grep'Bcast'|tr-d'[a-zA-Z]'|cut-d:-f2,3,4
10.1.1.1255.255.255.0
[root@servershell01]#ifconfigeth0|grep'Bcast'|tr-d'[a-zA-Z]'|cut-d:-f2,3,4|tr':''
'
10.1.1.1
10.1.1.255
255.255.255.0
[root@servershell01]#ifconfigeth0|grep'HWaddr'|cut-d:-f2-|cut-d''-f4
0029AE:54

#ifconfigeth1|grepBcast|cut-d:-f2|cut-d''-f1
#ifconfigeth1|grepBcast|cut-d:-f2|tr-d'[a-zA-Z]'
#ifconfigeth1|grepBcast|tr-d'[:a-zA-Z]'|tr'''@'|tr-s'@'|tr'@''
'|grep-v^$
#ifconfigeth0|grep'Bcast'|tr-d[]|tr'[:]''
'|grep-v^$
#ifconfigeth1|grepHWaddr|cut-d''-f11
#ifconfigeth0|grepHWaddr|tr-s''|cut-d''-f5
#ifconfigeth1|grepHWaddr|tr-s''|cut-d''-f5

将系统中所有普通用户的用户名、密码和默认shell保存到一个文件中,要求用户名密码和默认shell之间用tab键分割

[root@servershell01]#grep'bash$'passwd|grep-v'^root'|cut-d:-f1,2,7|tr':''	'
stu1x/bin/bash
codex/bin/bash
kefux/bin/bash
kefu1x/bin/bash
kefu2x/bin/bash
user01x/bin/bash
stu2x/bin/bash
[root@servershell01]#grepbash$passwd|grep-viE'root|mysql'|cut-d:-f1,2,7|tr':''	'|teea.txt

注释:
-E匹配扩展正则表达式,|代表或者,是一个扩展正则

2. 编程语言分类

编译型语言:

==程序在执行之前需要一个专门的编译过程==,把程序编译成为机器语言文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差些。如C、C++

解释型语言:

程序不需要编译,程序在运行时由==解释器==翻译成机器语言,每执行一次都要翻译一次。因此效率比较低。比如Python/JavaScript/ Perl /ruby/Shell等都是解释型语言。

78bf04fa-ac4b-11ed-bfe3-dac502259ad0.png

/语言分类

总结:

编译型语言比解释型语言==速度较快==,但是不如解释型语言==跨平台性好==。如果做底层开发或者大型应用程序或者操作系开发一==般都用编译型语言==;如果是一些服务器脚本及一些辅助的接口,对速度要求不高、对各个平台的==兼容性有要求==的话则一般都用==解释型语言==。

3. shell介绍

78e43e6e-ac4b-11ed-bfe3-dac502259ad0.png

00_shell介绍

总结:

==shell就是人机交互的一个桥梁==

shell的种类

[root@MissHou~]#cat/etc/shells
/bin/sh#是bashshell的一个快捷方式
/bin/bash#bashshell是大多数Linux默认的shell,包含的功能几乎可以涵盖shell所有的功能
/sbin/nologin#表示非交互,不能登录操作系统
/bin/dash#小巧,高效,功能相比少一些
/bin/tcsh#是csh的增强版,完全兼容csh
/bin/csh#具有C语言风格的一种shell,具有许多特性,但也有一些缺陷

用户在终端(终端就是bash的接口)输入命令

|
bash //bash就是shell的一种类型(bash shell)
|
kernel
|
物理硬件

4. shell脚本

什么是shell脚本?

一句话概括

简单来说就是将需要执行的命令保存到文本中,==按照顺序执行==。它是解释型的,意味着不需要编译。

准确叙述

若干命令 + 脚本的基本格式 + 脚本特定语法 + 思想= shell脚本

什么时候用到脚本?

重复化、复杂化的工作,通过把工作的命令写成脚本,以后仅仅需要执行脚本就能完成这些工作。

①自动化分析处理

②自动化备份

③自动化批量部署安装

④等等…

如何学习shell脚本?

尽可能记忆更多的命令

掌握脚本的标准的格式(指定魔法字节、使用标准的执行方式运行脚本)

必须==熟悉掌握==脚本的基本语法(重点)

脚本的基本写法:

#!/bin/bash
//脚本第一行,#!魔法字符,指定脚本代码执行的程序。即它告诉系统这个脚本需要什么解释器来执行,也就是使用哪一种Shell

//以下内容是对脚本的基本信息的描述
#Name:名字
#Desc:描述describe
#Path:存放路径
#Usage:用法
#Update:更新时间

//下面就是脚本的具体内容
commands
...

脚本执行方法:

标准脚本执行方法(建议):(魔法字节指定的程序会生效)

[root@MissHoushell01]#cat1.sh
#!/bin/bash
#xxxx
#xxx
#xxx
hostname
date
[root@MissHoushell01]#chmod+x1.sh
[root@MissHoushell01]#ll
total4
-rwxr-xr-x1rootroot42Jul2214:401.sh
[root@MissHoushell01]#/shell/shell01/1.sh
MissHou.itcast.cc
SunJul221400CST2018
[root@MissHoushell01]#./1.sh
MissHou.itcast.cc
SunJul221430CST2018

非标准的执行方法(不建议):(魔法字节指定的程序不会运作)

~~~shell
[root@MissHou shell01]# bash 1.sh
MissHou.itcast.cc
Sun Jul 22 1451 CST 2018
[root@MissHou shell01]# sh 1.sh
MissHou.itcast.cc
Sun Jul 22 1401 CST 2018
[root@MissHou shell01]#
[root@MissHou shell01]# bash -x 1.sh

hostname
MissHou.itcast.cc

date
Sun Jul 22 1420 CST 2018

-x:一般用于排错,查看脚本的执行过程
-n:用来查看脚本的语法是否有问题

注意:如果脚本没有加可执行权限,不能使用标准的执行方法执行,bash 1.sh

其他:
[root@server shell01]# source 2.sh
server
Thu Nov 22 1550 CST 2018
[root@server shell01]# . 2.sh
server
Thu Nov 22 1507 CST 2018

source 和 . 表示读取文件,执行文件里的命令
~~~

5. bash基本特性

5.1 命令和文件自动补全

Tab只能补全命令和文件 (RHEL6/Centos6)

5.2 常见的快捷键

^c终止前台运行的程序
^z将前台运行的程序挂起到后台
^d退出等价exit
^l清屏
^a|home光标移到命令行的最前端
^e|end光标移到命令行的后端
^u删除光标前所有字符
^k删除光标后所有字符
^r搜索历史命令

5.3 常用的通配符(重点)

*:匹配0或多个任意字符
?:匹配任意单个字符
[list]:匹配[list]中的任意单个字符
[!list]:匹配除list中的任意单个字符
{string1,string2,...}:匹配string1,string2或更多字符串

举例:
touchfile{1..3}
touchfile{1..13}.jpg
#lsfile*
#ls*.jpg
#llfile?
#llfile?.jpg
#llfile??.jpg
#llfile1?.jpg
#llfile?.jpg
#llfile[1023].jpg
#llfile[0-13].jpg
#llfile1[0-9].jpg
#llfile[0-9].jpg
#llfile?[1-13].jpg
#llfile[1,2,3,10,11,12].jpg
#llfile1{11,10,1,2,3}.jpg
#llfile{1..10}.jpg
#llfile{1...10}.jpg

5.4 bash中的引号(重点)

双引号"" :会把引号的内容当成整体来看待,允许通过符号引用其他变量值

  • 单引号′′:会把引号的内容当成整体来看待,禁止引用其他变量值,shell中特殊符号都被视为普通字符
  • 反撇号‘‘:反撇号和()一样,引号或括号里的命令会优先执行,如果存在嵌套,反撇号不能用

    [root@serverdir1]#echo"$(hostname)"
    server
    [root@serverdir1]#echo'$(hostname)'
    $(hostname)
    [root@serverdir1]#echo"helloworld"
    helloworld
    [root@serverdir1]#echo'helloworld'
    helloworld
    
    [root@serverdir1]#echo$(date+%F)
    2018-11-22
    [root@serverdir1]#echo`echo$(date+%F)`
    2018-11-22
    [root@serverdir1]#echo`date+%F`
    2018-11-22
    [root@serverdir1]#echo`echo`date+%F``
    date+%F
    [root@serverdir1]#echo$(echo`date+%F`)
    2018-11-22
    

    变量的定义

    1. 变量的分类

    本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。

    环境变量:当前进程有效,并且能够被子进程调用。

    查看当前用户的环境变量 env

    查询当前用户的所有变量(临时变量与环境变量) **set **

    **export //将当前变量变成环境变量 **

    [root@MissHoutmp]#exportA=hello//临时将一个本地变量(临时变量)变成环境变量
    [root@MissHoutmp]#env|grep^A
    A=hello
    
    永久生效:
    vim/etc/profile或者~/.bashrc
    exportA=hello
    或者
    A=hello
    exportA
    
    说明:系统中有一个变量PATH,环境变量
    exportPATH=/usr/local/mysql/bin:$PATH
    

    全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.

    $HOME/.bashrc当前用户的bash信息(aliase、umask等)
    $HOME/.bash_profile当前用户的环境变量()
    oracle——>oracle用户——>$oracle/.bash_profile——>exporthome_install=/u01/app/xxx
    
    $HOME/.bash_logout每个用户退出当前shell时最后读取的文件
    
    /etc/bashrc使用bashshell用户全局变量
    grep--color=auto
    umask
    
    /etc/profile系统和每个用户的环境变量信息
    
    mycat_home=/usr/local/mycat/bin
    exportmycat_home
    执行mycat命令
    #mycat
    $mycat
    
    用户登录系统读取相关文件的顺序:
    /etc/profile——>$HOME/.bash_profile——>$HOME/.bashrc——>/etc/bashrc——>$HOME/.bash_logout
    
    source/etc/bashrc
    

    系统变量(内置bash中变量):shell本身已经固定好了它的名字和作用.

    $?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错
    若退出状态值为0,表示命令运行成功
    若退出状态值为127,表示commandnotfound
    若退出状态值为126,表示找到了该命令但无法执行(权限不够)
    若退出状态值为1&2,表示没有那个文件或目录
    
    $$:当前所在进程的进程号 echo $$ eg:kill -9 `echo $$`= exit 退出当前会话
    $!:后台运行的最后一个进程号(当前终端)# gedit &
    !$调用最后一条命令历史中的参数
    !!调用最后一条命令历史
    
    
    $#:脚本后面接的参数的个数
    $*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
    $@:脚本后面所有参数,参数是独立的,也是全部输出
    
    $0:当前执行的进程/程序名 echo $0
    $1~$9位置参数变量
    ${10}~${n}扩展位置参数变量第10个位置变量必须用{}大括号括起来
    ./1.shabc
    
    [root@MissHoushell01]#cat2.sh
    #!/bin/bash
    #xxxx
    echo"$0=$0"
    echo"$#=$#"
    echo"$*=$*"
    echo"$@=$@"
    echo"$1=$1"
    echo"$2=$2"
    echo"$3=$3"
    echo"$11=${11}"
    echo"$12=${12}"
    
    了解$*和$@的区别:
    $*:表示将变量看成一个整体
    $@:表示变量是独立的
    
    #!/bin/bash
    foriin"$@"
    do
    echo$i
    done
    
    echo"======我是分割线======="
    
    foriin"$*"
    do
    echo$i
    done
    
    [root@MissHoushell01]#bash3.shabc
    a
    b
    c
    ======我是分割线=======
    abc
    

    2. 什么时候需要定义变量?

    如果某个内容需要多次使用,并且在代码中重复出现,那么可以用变量代表该内容。这样在修改内容的时候,仅仅需要修改变量的值。

    在代码运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量。

    3. 变量的定义规则

    1. 默认情况下,shell里定义的变量是不分类型的,可以给变量赋与任何类型的值;等号两边不能有空格,对于有空格的字符串做为赋值时,要用引号引起来
    变量名=变量值
    
    2. 变量的获取方式:$变量名${变量名}
    [root@MissHoushell01]#a=12345678
    [root@MissHoushell01]#echo$a
    12345678
    [root@MissHoushell01]#echo${a}
    12345678
    [root@MissHou shell01]# echo ${a3} a表示变量名;2表示从第3个字符开始;3表示后面3个字符
    345
    
    如果获取变量的全部两个都可以;如果获取变量的某一部分,用${}
    
    3.取消变量:unset变量名
    
    4.变量名区分大小写,同名称但大小写不同的变量名是不同的变量
    5.变量名可以是字母或数字或下划线,但是不能以数字开头或者特殊字符
    [root@MissHoushell01]#1a=hello
    -bash:1a=hello:commandnotfound
    [root@MissHoushell01]#?a=hello
    -bash:?a=hello:commandnotfound
    [root@MissHoushell01]#_a=hello
    [root@MissHoushell01]#echo$_a
    hello
    
    6.命令的执行结果可以保存到变量
    [root@servershell01]#kernel=`uname-r`
    [root@servershell01]#echo$kernel
    2.6.32-431.el6.x86_64
    [root@servershell01]#name=$(uname-n)
    [root@servershell01]#echo$name
    server.itcast.cc
    
    7.有类型变量declare
    -i将变量看成整数
    -r使变量只读readonly
    -x标记变量通过环境导出export
    -a 指定为索引数组(普通数组);查看普通数组
    -A 指定为关联数组;查看关联数组
    
    [root@servershell01]#a=10
    [root@servershell01]#b=20
    [root@servershell01]#echo$a+$b
    10+20
    
    [root@servershell01]#declare-ia=2
    [root@servershell01]#declare-ib=4
    [root@servershell01]#declare-ic=$a+$b
    [root@servershell01]#echo$c
    6
    
    [root@servershell01]#AAAA=hello
    [root@servershell01]#exportAAAA
    [root@servershell01]#env|grepAAAA
    AAAA=hello
    [root@servershell01]#declare-xBBBB=hello
    [root@servershell01]#env|grepBBBB
    BBBB=hello
    
    
    8.数组
    普通数组:只能使用整数作为数组索引(元素的下标)
    关联数组:可以使用字符串作为数组索引(元素的下标)
    
    普通数组定义:用括号来表示数组,数组元素(变量)用“空格”符号分割开。定义数组的一般形式为:
    一次赋一个值:
    变量名=变量值
    array[0]=v1
    array[1]=v2
    array[3]=v3
    一次赋多个值:
    array=(var1var2var3var4)
    array1=(`cat/etc/passwd`)//将文件中每一行赋值给array1数组
    array2=(`ls/root`)
    array3=(harryamyjack"MissHou")
    array4=(1234"helloworld"[10]=linux)
    
    读取数组:
    ${array[i]}i表示元素的下标
    使用@或*可以获取数组中的所有元素:
    获取第一个元素
    echo${array[0]}
    echo${array[*]}获取数组里的所有元素
    echo${#array[*]}获取数组里所有元素个数
    echo${!array[@]}获取数组元素的索引下标
    echo ${array[@]2}访问指定的元素;1代表从下标为1的元素开始获取;2代表获取后面几个元素
    
    
    [root@servershell01]#array[0]=var1
    [root@servershell01]#array[1]=var2
    [root@servershell01]#array[2]=var3
    [root@servershell01]#array1=(uu1uu2uu3uu4)
    [root@servershell01]#ls
    1.sh2.sh3.sh4.shpasswd
    [root@servershell01]#array2=(`ls./`)
    [root@servershell01]#array3=(jackharry"MissHou"[5]=tom)
    
    查看普通数组信息:
    [root@servershell01]#declare-a
    declare-aarray='([0]="var1"[1]="var2"[2]="var3")'
    declare-aarray1='([0]="uu1"[1]="uu2"[2]="uu3"[3]="uu4")'
    declare-aarray2='([0]="1.sh"[1]="2.sh"[2]="3.sh"[3]="4.sh"[4]="passwd")'
    declare-aarray3='([0]="jack"[1]="harry"[2]="MissHou"[5]="tom")'
    [root@servershell01]#
    [root@servershell01]#
    [root@servershell01]#echo${array[*]}
    var1var2var3
    [root@servershell01]#echo${array[@]}
    var1var2var3
    [root@servershell01]#echo${array[2]}
    var3
    [root@servershell01]#echo${array2[@]}
    1.sh2.sh3.sh4.shpasswd
    [root@servershell01]#echo${array2[3]}
    4.sh
    [root@servershell01]#
    [root@servershell01]#echo${array2[*]2}
    3.sh4.sh
    [root@servershell01]#echo${#array2[*]}
    5
    [root@servershell01]#echo${!array2[*]}
    01234
    [root@servershell01]#echo${!array3[*]}
    0125
    
    
    关联数组定义:
    首先声明关联数组
    declare-Aasso_array1
    declare-Aasso_array2
    declare-Aasso_array3
    
    数组赋值:
    一次赋一个值:
    数组名[索引|下标]=变量值
    [root@server~]#asso_array1[linux]=one
    [root@server~]#asso_array1[java]=two
    [root@server~]#asso_array1[php]=three
    一次赋多个值:
    [root@server~]#asso_array2=([name1]=harry[name2]=jack[name3]=amy[name4]="MissHou")
    查看关联数组:
    [root@server~]#declare-A
    declare-Aasso_array1='([php]="three"[java]="two"[linux]="one")'
    declare-Aasso_array2='([name3]="amy"[name2]="jack"[name1]="harry"[name4]="MissHou")'
    
    [root@server~]#echo${asso_array1[linux]}
    one
    [root@server~]#echo${asso_array1[php]}
    three
    [root@server~]#echo${asso_array1[*]}
    threetwoone
    [root@server~]#echo${!asso_array1[*]}
    phpjavalinux
    [root@server~]#echo${#asso_array1[*]}
    3
    [root@server~]#echo${#asso_array2[*]}
    4
    [root@server~]#echo${!asso_array2[*]}
    name3name2name1name4
    
    
    9.交互式定义变量的值read主要用于让用户去定义变量值
    -p提示信息
    -n字符数(限制变量值的字符数)
    -s不显示
    -t超时(默认单位秒)(限制用户输入变量值的超时时间)
    
    [root@MissHoushell01]#cat1.txt
    10.1.1.1255.255.255.0
    
    [root@MissHoushell01]#read-p"InputyourIPandNetmask:"ipmask< 1.txt 
    [root@MissHou shell01]# echo $ip
    10.1.1.1
    [root@MissHou shell01]# echo $mask
    255.255.255.0
    
    
    10. 其他变量(扩展)
    1)取出一个目录下的目录和文件:dirname和 basename 
    2)变量"内容"的删除和替换
    一个“%”代表从右往左去掉一个/key/
    两个“%%”代表从右往左最大去掉/key/
    一个“#”代表从左往右去掉一个/key/
    两个“##”代表从左往右最大去掉/key/
    
    # A=/root/Desktop/shell/mem.txt 
    # echo $A
    /root/Desktop/shell/mem.txt
    # dirname $A   取出目录
    /root/Desktop/shell
    # basename $A  取出文件
    mem.txt
    
    # url=www.taobao.com
    # echo ${#url}             获取变量的长度
    # echo ${url#*.}
    # echo ${url##*.}
    # echo ${url%.*}
    # echo ${url%%.*}
    
    ++++++++++++++++++++++++++++++++++++++++++++++++++
    以下内容自己完成:
    替换:/ 和 //
     1015  echo ${url/ao/AO}
     1017  echo ${url//ao/AO}   贪婪替换
    
    替代: - 和 :-  +和:+
     1019  echo ${abc-123}
     1020  abc=hello
     1021  echo ${abc-444}
     1022  echo $abc
     1024  abc=
     1025  echo ${abc-222}
    
    ${变量名-新的变量值} 或者 ${变量名=新的变量值}
    变量没有被赋值:会使用“新的变量值“ 替代
    变量有被赋值(包括空值): 不会被替代
    
     1062  echo ${ABC:-123}
     1063  ABC=HELLO
     1064  echo ${ABC:-123}
     1065  ABC=
     1066  echo ${ABC:-123}
    
    ${变量名:-新的变量值} 或者 ${变量名:=新的变量值}
    变量没有被赋值或者赋空值:会使用“新的变量值“ 替代
    变量有被赋值: 不会被替代
    
     1116  echo ${abc=123}
     1118  echo ${abc:=123}
    
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc:+123}
    
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc:+123}
    123
    [root@server ~]# abc=
    [root@server ~]# echo ${abc:+123}
    
    ${变量名+新的变量值}
    变量没有被赋值或者赋空值:不会使用“新的变量值“ 替代
    变量有被赋值: 会被替代
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc+123}
    
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc+123}
    123
    [root@server ~]# abc=
    [root@server ~]# echo ${abc+123}
    123
    ${变量名:+新的变量值}
    变量没有被赋值:不会使用“新的变量值“ 替代
    变量有被赋值(包括空值): 会被替代
    
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc?123}
    -bash: abc: 123
    
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc?123}
    hello
    [root@server ~]# abc=
    [root@server ~]# echo ${abc?123}
    
    ${变量名?新的变量值}
    变量没有被赋值:提示错误信息
    变量被赋值(包括空值):不会使用“新的变量值“ 替代
    
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc:?123}
    -bash: abc: 123
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc:?123}
    hello
    [root@server ~]# abc=
    [root@server ~]# echo ${abc:?123}
    -bash: abc: 123
    
    ${变量名:?新的变量值}
    变量没有被赋值或者赋空值时:提示错误信息
    变量被赋值:不会使用“新的变量值“ 替代
    
    说明:?主要是当变量没有赋值提示错误信息的,没有赋值功能
    

    简单的四则运算

    算术运算:默认情况下,shell就只能支持简单的==整数==运算

    +-*/%(取模,求余数)
    
    Bashshell的算术运算有四种方式:
    1.使用$(())
    2.使用$[]
    3.使用expr外部程式
    4.使用let命令
    
    注意:
    n=1
    letn+=1等价于letn=n+1
    
    
    
    思考:能不能用shell做小数运算?
    [root@servershell01]#echo1+1.5|bc
    2.5
    
    
    i++和++i(了解)
    对变量的值的影响:
    [root@node1~]#i=1
    [root@node1~]#leti++
    [root@node1~]#echo$i
    2
    [root@node1~]#j=1
    [root@node1~]#let++j
    [root@node1~]#echo$j
    2
    
    对表达式的值的影响:
    [root@node1~]#unsetij
    [root@node1~]#i=1;j=1
    [root@node1~]#letx=i++先赋值,再运算
    [root@node1~]#lety=++j先运算,再赋值
    [root@node1~]#echo$i
    2
    [root@node1~]#echo$j
    2
    [root@node1~]#echo$x
    1
    [root@node1~]#echo$y
    2
    

    总结:

    $(())$[]
    expr注意空格,*要进行转义
    
    letn+=1等价letn=n+1
    letn=n**5n有初值,然后求次幂
    
    i++++i
    对变量本身没有影响(自己+1);
    表达式中有影响;i++先赋值再运算++i先运算再赋值
    letx=i++letx=++i
    

    条件判断

    1. 语法格式

    格式1:==test== 条件表达式

    格式2:[条件表达式 ]

    格式3:[[条件表达式 ]] 支持正则 =~

    说明:

    man test去查看,很多的参数都用来进行条件判断

    2. 条件判断相关参数

    与文件存在与否的判断

    -e是否存在不管是文件还是目录,只要存在,条件就成立
    -f是否为普通文件
    -d是否为目录
    -Ssocket
    -ppipe
    -ccharacter
    -bblock
    -L软link
    
    三种语法格式:
    test-efile只要文件存在条件为真
    [-d/shell01/dir1]判断目录是否存在,存在条件为真
    [!-d/shell01/dir1]判断目录是否存在,不存在条件为真
    [[-f/shell01/1.sh]]判断文件是否存在,并且是一个普通的文件
    
    -s判断文件是否有内容(大小),非空文件条件满足
    说明:-s表示非空,!-s 表示空文件
    说明:1.sh文件里有内容的。
    [root@servershell01]#test-s1.sh
    [root@servershell01]#echo$?
    0
    [root@servershell01]#touchaaa
    [root@servershell01]#cataaa
    [root@servershell01]#test-saaa
    [root@servershell01]#echo$?
    1
    [root@servershell01]#test!-saaa
    [root@servershell01]#echo$?
    0
    [root@servershell01]#test!-s1.sh
    [root@servershell01]#echo$?
    1
    

    文件权限相关的判断

    -r当前用户对其是否可读
    -w当前用户对其是否可写
    -x当前用户对其是否可执行
    -u是否有suid
    -g是否sgid
    -k是否有t位
    

    两个文件的比较判断

    file1-ntfile2比较file1是否比file2新
    file1-otfile2比较file1是否比file2旧
    file1-effile2比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode
    
    testfile1-ntfile2
    [file1-otfile2]
    

    整数之间的判断

    -eq相等
    -ne不等
    -gt大于
    -lt小于
    -ge大于等于
    -le小于等于
    

    字符串之间的判断

    -z是否为空字符串字符串长度为0,就成立
    -n是否为非空字符串只要字符串非空,就是成立
    string1=string2是否相等
    string1!=string2不等
    
    [root@servershell01]#AAA=hello
    [root@servershell01]#BBB=world
    [root@servershell01]#test-z$AAA
    [root@servershell01]#echo$?
    1
    [root@servershell01]#test-n$AAA
    [root@servershell01]#echo$?
    0
    
    [root@servershell01]#[$AAA=$BBB]
    [root@servershell01]#echo$?
    1
    [root@servershell01]#[$AAA!=$BBB]
    [root@servershell01]#echo$?
    0
    

    多重条件判断

    逻辑判断符号:
    -a和&&(and逻辑与)两个条件同时满足,整个大条件为真
    -o和||(or逻辑或)两个条件满足任意一个,整个大条件为真
    
    
    [1-eq1-a1-ne0]整个表达式为真
    [1-eq1]&&[1-ne0]
    
    
    [1-eq1-o1-ne1]整个表达式为真
    [1-eq1]||[1-ne1]
    
    [root@servershell01]#[1-eq0]&&echotrue||echofalse
    false
    [root@servershell01]#[1-eq1]&&echotrue||echofalse
    true
    
    &&:前面的表达式为真
    ||:前面的表达式为假
    
    
    
    总结:
    1、;&&||都可以用来分割命令或者表达式
    2、;完全不考虑前面的语句是否正确执行,都会执行;号后面的内容
    3、&&需要考虑&&前面的语句的正确性,前面语句正确执行才会执行&&后的内容;反之亦然
    make&&makeinstall
    4、||需要考虑||前面的语句的非正确性,前面语句执行错误才会执行||后的内容;反之亦然
    5、如果&&和||一起出现,从左往右依次看,按照以上原则
    

    3. 示例

    示例:
    数值比较:
    [root@server~]#[$(id-u)-eq0]&&echo"theuserisadmin"
    [root@server~]$[$(id-u)-ne0]&&echo"theuserisnotadmin"
    [root@server~]$[$(id-u)-eq0]&&echo"theuserisadmin"||echo"theuserisnotadmin"
    
    [root@server~]#uid=`id-u`
    [root@server~]#test$uid-eq0&&echothisisadmin
    thisisadmin
    [root@server~]#[$(id-u)-ne0]||echothisisadmin
    thisisadmin
    [root@server~]#[$(id-u)-eq0]&&echothisisadmin||echothisisnotadmin
    thisisadmin
    [root@server~]#su-stu1
    [stu1@server~]$[$(id-u)-eq0]&&echothisisadmin||echothisisnotadmin
    thisisnotadmin
    [stu1@server~]$
    
    
    类C风格的数值比较:
    注意:在(())中,=表示赋值;==表示判断
    1159((1==2));echo$?
    1160((1<2));echo $?
     1161  ((2>=1));echo$?
    1162((2!=1));echo$?
    1163((`id-u`==0));echo$?
    
    1209((a=123));echo$a
    1210unseta
    1211((a==123));echo$?
    
    
    
    字符串比较:
    注意:双引号引起来,看作一个整体;=和==在[字符串]比较中都表示判断
    1196a='helloworld';b=world
    1197[$a=$b];echo$?
    1198["$a"="$b"];echo$?
    1199["$a"!="$b"];echo$?
    1200["$a"!=="$b"];echo$?错误
    1201["$a"=="$b"];echo$?
    1202test"$a"!="$b";echo$?
    
    
    
    思考:[]和[[]]有什么区别?
    
    1213a=
    1214test-z$a;echo$?
    1215a=hello
    1216test-z$a;echo$?
    1217test-n$a;echo$?
    1217test-n"$a";echo$?
    
    #[''=$a];echo$?
    -bash:[::unaryoperatorexpected
    2
    #[[''=$a]];echo$?
    0
    
    
    1278[1-eq0-a1-ne0];echo$?
    1279[1-eq0&&1-ne0];echo$?
    1280[[1-eq0&&1-ne0]];echo$?

    审核编辑:汤梓红
  • 声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
    • Linux
      +关注

      关注

      87

      文章

      10990

      浏览量

      206738
    • 编写
      +关注

      关注

      0

      文章

      29

      浏览量

      8373
    • python
      +关注

      关注

      51

      文章

      4677

      浏览量

      83473
    • Shell
      +关注

      关注

      1

      文章

      358

      浏览量

      22903
    • 脚本
      +关注

      关注

      1

      文章

      372

      浏览量

      14636

    原文标题:【建议收藏】一文吃透shell编写工具及基本法则!

    文章出处:【微信号:浩道linux,微信公众号:浩道linux】欢迎添加关注!文章转载请注明出处。

    收藏 人收藏

      评论

      相关推荐

      喇叭摆位基本法

      本文讲讲喇叭摆位的基本法 首先要做到耳平高音单元    喇叭即扬声器或音箱(国内用词),人们大都将之概括地分成两大类别。是座
      发表于 08-27 09:22

      shell编程之shell是什么

      种接口。它接收用户输入的命令并把它送入内核去执行。实际上Shell个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,
      发表于 11-26 16:00

      如何编写Shell脚本命令?

      编写Shell脚本命令
      发表于 06-18 14:00

      开关电源芯片TB6812的特点和应用

      优胜劣汰是竞争的基本法则,企业要生存、求发展,就必须苦练内功,采取各种措施降低成本,只有以低于竞争对手的成本进行生产经营。才能在竞争中立于不败之地。低成本可以说是中国的传统美德,银联宝科技是家注重于低成本的电源芯片公司,TB6812广泛应用在12V1A,5V1A的方案上
      发表于 10-29 07:42

      Shell与变量的相关资料分享

      笔记系列嵌入式系统方向学习笔记1嵌入式系统方向学习笔记2嵌入式系统方向学习笔记3嵌入式系统方向学习笔记4章目录笔记系列前言、开发工具的总结二、Shell与变量1.
      发表于 12-22 08:11

      在单片机中实现类似shell的命令行工具

      在单片机中实现类似shell的命令行工具如果在单片机编程过程中有个类似linux的shell命令工具可以通过串口调试助手输入命令然后运行
      发表于 01-05 06:18

      电脑维修的基本法则

      随着电脑等消费性电子产品逐渐普及,电脑维修已成为硬件电路板维修中最常见的一种,能够掌握基本的电脑维修法则,对每一个普通的维修工程师甚至电脑使用者都是相当重要
      发表于 10-22 17:14 3259次阅读

      静电防治培训教材

      静电放电简介 静电放电的模型 ESD的影响 静电防治专有名词介绍 静电防治材料定义 静电防治基本法则 ESDA测试标準及介绍
      发表于 04-21 18:04 0次下载
      静电防治培训教材

      u-boot中Hush shell的功能及编写脚本的方法介绍

      了解u-boot中Hush shell的功能,以及如何为其编写脚本。 说明了存储和检索脚本的方法。
      的头像 发表于 11-22 07:00 5068次阅读

      PCB设计的基本法则解析

      此外,多边形对于电路板敷铜至关重要,多重网格电路板在进行多边形敷铜时一般会产生多边形填充偏差,虽然不如基于单个网格那么标准,但却可提供超越所需的电路板使用寿命。
      发表于 11-13 15:36 833次阅读

      分享PLC控制柜定期保养维护基本法则

      对于需要长期归档的数据(比如军工行业的历史趋势曲线数据),可以将历史趋势数据备份到移动硬盘,然后关闭基于Windows的操作系统,比如带wincc intouch的HMI系统;然后再断总电源;
      的头像 发表于 03-09 11:41 2853次阅读

      电源PCB布板的10个基本法则资料下载

      电子发烧友网为你提供电源PCB布板的10个基本法则资料下载的电子资料下载,更有其他相关的电路图、源代码、课件教程、中文资料、英文资料、参考设计、用户指南、解决方案等资料,希望可以帮助到广大的电子工程师们。
      发表于 04-07 08:55 23次下载
      电源PCB布板的10个<b class='flag-5'>基本法则</b>资料下载

      【划重点】电源PCB布板的10个基本法则

      电容模型 电容并联高频特性 电感模型
      发表于 02-11 14:06 3次下载
      【划重点】电源PCB布板的10个<b class='flag-5'>基本法则</b>!

      基于PCB布板基本法则

      电容模型 电容并联高频特性 电感模型 电感特性 镜象面概念 高频交流电流环路 过孔 (VIA) 的例子 PCB板层分割 降压式(BUCK)电源:功率部分电流和电压波形 降压式电源排版差的例子 电路等效图 PCB Trace - Via 电感估算 焊盘(PAD)和旁路电容的放置 降压式电源排版的例子 降压式电源排版的例子       审核编辑:彭静
      的头像 发表于 10-09 10:21 603次阅读

      Linux命令行与shell脚本编写

      Linux命令行与shell脚本编写
      发表于 01-11 16:50 4次下载