Shell

在这里插入图片描述

一. Shell 基础

1.1 什么是 Shell

Shell 是命令解释器( command interpreter ),是 Unix 操作系统的用户接口,程序从用户接口得到输入信息,Shell 将用户程序及其输入翻译成操作系统内核( kernel )能够识别的指令,并且操作系统内核执行完将返回的输出通过 Shell 再呈现给用户,如图 8.1 展示了用户、Shell 和内核的关系:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CjWDqRkC-1592916007444)(assets/image-20191112111059349.png)]

图 8.1 Shell、用户、内核之间的关系

Shell 也是一门编程语言,即 Shell 脚本,Shell 是解释执行的脚本语言,可直接调用 Linux 命令。类似于JS。

1.2 Shell 基本操作

学习 Shell 之前我们先了解一些 Shell 的基本操作,比如自动补全和历史记录等。

1.2.1 查看历史命令

在 Linux 中执行过的操作都会有记录,默认可以记录 1000 条历史记录。历史记录保存在用户主目录下的 .bash_history 文件中。注意:只有用户正常退出当前的 Shell 的时候,在当前 Shell 中执行的命令才会记录到文件中。

基本操作

  1. 查看历史记录【文件:.bash_history】
## 注意:当前操作目录必须是用户主目录
[root@admin ~]# cd ~
[root@admin ~]# more .bash_history
  1. 执行上一次执行的命令【命令:!!】
## 先执行 pwd 命令
[root@admin ~]# pwd
/root
## 然后执行 !! 命令就会出现下面的内容
[root@admin ~]# !!
pwd
/root
  1. 执行历史记录的第n个命令【命令:!n】
[root@admin ~]# !1
cd /opt/apps/
[root@admin apps]# 
  1. 执行最近一次以Word开头的命令【命令:!Word】
[root@admin ~]# !p
pwd
/root
[root@admin ~]# 

1.2.2 命令和自动补全

Tab 键可以帮助我们自动补全一个命令、路径或者是文件名,连续两次 Tab 键会把检测到的全部列出来。

# 输入 systemc 按Tab键即可补充完整,然后双击 Tab 即可显示其他
[root@admin ~]# systemctl
anaconda-ks.cfg  .bashrc          .tcshrc
.bash_history    .cshrc           .viminfo
.bash_logout     .m2/             张三/
.bash_profile    .subversion/  

1.2.3 别名

别名 Alias 就类似于外号,其实就是为了方便记忆而存在。

# 设置pwd的别名为aaa
[root@admin ~]# alias aaa='pwd'
# 执行aaa这个命令其实就是在执行pwd命令
[root@admin ~]# aaa
/root
# 取消aaa别名的设置
[root@admin ~]# unalias aaa
# 再次执行aaa命令,发现不可用
[root@admin ~]# aaa
-bash: aaa: 未找到命令

1.2.4 通配符

bash下使用 * 表示任意多个字符,使用 ? 匹配一个字符。

[root@admin data]# ls
bbbb  test111  test112  test222  test3  test333  test4
[root@admin data]# ls test*
test111  test112  test222  test3  test333  test4
[root@admin data]# ls test?
test3  test4

1.2.5 in/out 重定向

输入重定向为 <,不常用。输出重定向为 >,还有输出追加重定向为 >>。错误重定向为 2>

# 第一次输出到bbbb文件
[root@admin data]# echo 1234 > bbbb
[root@admin data]# more bbbb
1234
# 第二次输出到bbbb文件,再次查看,之前内容消失,其实就是覆盖
[root@admin data]# echo 5678 > bbbb
[root@admin data]# more bbbb
5678
# 第三次使用追加到bbbb文件,再次查看,之前内容不覆盖
[root@admin data]# echo 9876 >> bbbb
[root@admin data]# more bbbb
5678
9876
# 第一次执行 ppppp命令报错
[root@admin data]# ppppp
-bash: ppppp: 未找到命令
# 第二次使用错误输出重定向到文件,不报错
[root@admin data]# ppppp 2> error.log
[root@admin data]# ls
bbbb       test111  test222  test333
error.log  test112  test3    test4
# 再次查看错误信息进入到了日志中
[root@admin data]# more error.log 
-bash: ppppp: 未找到命令

1.2.6 管道符

管道符其实就是 | ,用于将前一个指令的输出作为后一个指令的输入。

# 查看bbbb内容然后使用wc查看其行数,-w查看单词个数
[root@admin data]# cat bbbb | wc -l
2

1.2.7 作业控制

Ctrl+Z 可以让程序暂停,然后使用 fg 命令恢复,使用 jobs 查看当前暂停或者被后台运行的任务,使用 bg 让程序继续在后台运行。

1.3 变量

Shell 预设的变量一般都是大写,比如 PATHHOMEHOSTNAME 等。

[root@admin data]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/java/jdk1.8.0_221/bin:/usr/java/jdk1.8.0_221/jre/bin:/opt/maven-3.5.4/bin:/opt/findbugs-3.0.1/bin:/root/bin
[root@admin data]# echo $HOME
/root
[root@admin data]# echo $HOSTNAME
admin

1.3.1 env

env 命令可以列出系统预设的全部系统变量。

[root@admin data]# env
XDG_SESSION_ID=1
HOSTNAME=admin  #主机名
SELINUX_ROLE_REQUESTED=
TERM=xterm
SHELL=/bin/bash #当前用户的shell类型
HISTSIZE=1000   #历史记录数
SSH_CLIENT=192.168.100.1 8309 22
SELINUX_USE_CURRENT_RANGE=
OLDPWD=/opt
SSH_TTY=/dev/pts/0
JRE_HOME=/usr/java/jdk1.8.0_221/jre
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/java/jdk1.8.0_221/bin:/usr/java/jdk1.8.0_221/jre/bin:/opt/maven-3.5.4/bin:/opt/findbugs-3.0.1/bin:/root/bin
PWD=/opt/data #当前目录
JAVA_HOME=/usr/java/jdk1.8.0_221
LANG=zh_CN.UTF-8 #当前系统的语言环境
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
M2_HOME=/opt/maven-3.5.4
SHLVL=1
HOME=/root
LOGNAME=root #当前用户的登录名
CLASSPATH=.:/usr/java/jdk1.8.0_221/lib/dt.jar:/usr/java/jdk1.8.0_221/lib/tools.jar:/usr/java/jdk1.8.0_221/jre/lib/rt.jar
SSH_CONNECTION=192.168.100.1 8309 192.168.100.222 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
FINDBUGS_HOME=/opt/findbugs-3.0.1
_=/usr/bin/env

1.3.2 set

setenv 类似,只不过 set 可以查看到当前用户自定义的变量。当前 bash 中定义的变量只能在当前 bash 中使用,新开的会话窗口不能使用。

1.3.3 系统环境变量与用户环境变量

以下是几个文件的说明:

/etc/profile :这个文件预设了几个重要的变量,比如 PATHUSERLOGNAMEMATLINPUTRCHOSTNAMEHISTSIZEumask 等。

/etc/bashrc :预设了 umaskPS1

.bash_profile :定义该用户变量的配置,属于专属某一个用户的 shell 信息,当用户登录时,该文件仅仅执行一次。

.bashrc :当登录火美此打开新的 shell 的时候,该文件都会被执行。

.bash_history : 记录历史命令

.bash_logout :当退出 shell 时,执行该文件,一般用于清理程序。

1.4 Shell 的特殊符号

  • *

    表示任意多个任意字符。

  • ?

    表示任意一个字符。

  • #

    表示注释。

  • \

    脱义字符(转义字符)。比如 \* 表示字符 *

  • |

    管道符

  • $

    引用变量的值,比如:$PATH

  • ;

    如果一行想输入多个命令,可以使用分号隔开每个命令。

  • ~

    表示用户的主目录。

  • &

    如果想把一条命令放到后台执行,则需要加上 & 符号,常用于需要运行很长时间的命令。

  • []

    括号内可以是任意字符的组合

    [root@admin data]# ls test*
    test111  test112  test222  test3  test333  test4  testa  testaaa  testbbb
    [root@admin data]# ls test[1-9]
    test3  test4
    [root@admin data]# ls test[a-z]
    testa
    [root@admin data]# ls test[1-9a-z]
    test3  test4  testa
    
  • &&||

    这两个符号前后都可以跟一条命令,和 Java 中类似。

    [root@admin data]# ls test5 && touch test6
    ls: 无法访问test5: 没有那个文件或目录
    [root@admin data]# ls
    aaaa  error.log  test112  test3    test4  testaaa
    bbbb  test111    test222  test333  testa  testbbb
    [root@admin data]# ls test5 || touch test6
    ls: 无法访问test5: 没有那个文件或目录
    [root@admin data]# ls
    aaaa  error.log  test112  test3    test4  testa    testbbb
    bbbb  test111    test222  test333  test6  testaaa
    

1.5 其他命令

1.5.1 cut

cut命令用来显示行中的指定部分,删除文件中指定字段。cut 经常用来显示文件的内容。

常用选项

  • -b: 以字节为单位进行分割 ,仅显示行中指定字节范围的内容;
  • -c:仅显示行中指定范围的字符;
  • -d:指定字段的分隔符,默认的字段分隔符为“TAB”;
  • -f:显示指定字段的内容;
  • -n:与“-b”选项连用,不分割多字节字符;

基本案例

[root@admin data]# cat student 
No	Name	Age	Gender
1001	lisi	17	nan
1002	wangwu	18	nv
1005	zhaoliu	17	nan
1003	haha	18	nv
1007	hehe	17	nan
1004	xixi	17	nan
[root@admin data]# cut -f 2 student 
Name
lisi
wangwu
zhaoliu
haha
hehe
xixi
[root@admin data]# cat student | cut -f 1
No
1001
1002
1005
1003
1007
1004
[root@admin data]# cat teacher 
No Name lisi 17 nan
1002 wangwu 18 nv
1005 zhaoliu 17 nan
1003 haha 18 nv
1007 hehe 17 nan
1004 xixi 17 nan
[root@admin data]# cat teacher | cut -d ' ' -f 2
Name
lisi
wangwu
zhaoliu
haha
hehe
xixi

1.5.2 sort

sort 命令是在 Linux 里非常有用,它将文件进行排序,并将排序结果标准输出。sort 命令既可以从特定的文件,也可以从 stdin 中获取输入。

常用选项

  • -b:忽略每行前面开始出的空格字符;
  • -c:检查文件是否已经按照顺序排序;
  • -d:排序时,处理英文字母、数字及空格字符外,忽略其他的字符;
  • -f:排序时,将小写字母视为大写字母;
  • -m:将几个排序号的文件进行合并;gr
  • -n:依照数值的大小排序;
  • -r:以相反的顺序来排序;
  • -t<分隔字符>:指定排序时所用的栏位分隔字符;
  • -k : 排序所依据的列 ;

基本案例

[root@admin data]# cat teacher | sort -nk 3 -t' '
No Name Age Gender
1001 lisi 17 nan
1004 xixi 17 nan
1005 zhaoliu 17 nan
1007 hehe 17 nan
1002 wangwu 18 nv
1003 haha 18 nv
[root@admin data]# cat teacher | sort -nk 1 -t' '
No Name Age Gender
1001 lisi 17 nan
1002 wangwu 18 nv
1003 haha 18 nv
1004 xixi 17 nan
1005 zhaoliu 17 nan
1007 hehe 17 nan
[root@admin data]# cat teacher | sort -nrk 1 -t' '
1007 hehe 17 nan
1005 zhaoliu 17 nan
1004 xixi 17 nan
1003 haha 18 nv
1002 wangwu 18 nv
1001 lisi 17 nan
No Name Age Gender

1.5.3 wc

wc 命令用来计算数字 。

  • -c 或–bytes或——chars:只显示Bytes数;
  • -l 或——lines:只显示列数;
  • -w 或——words:只显示字数。

1.5.4 tee

类似于 > 重定向,只不过还会在控制台上显示数据。

[root@admin data]# echo aaa| tee bbbb 
aaa

1.5.5 uniq

删除重复行。

-c 选项经常使用,统计重复的行数

[root@admin data]# cat teacher | cut -d ' ' -f 3 | sort | uniq -c
      4 17
      2 18
      1 Age

二. Shell 高级

2.1 什么是 Shell 脚本

简单来说,Shell 脚本就是一堆命令的集合,再加上一些程序结构和语法。

2.1.1 第一个 Shell 脚本

几乎所有编程语言的教程都是从使用著名的 Hello World 开始的,出于对这种传统的尊重(或者说落入俗套),我们的第一个 Shell 脚本也输出 Hello World

步骤:

  1. 使用 vim 编辑器新建一个文件 s1.sh
[root@admin data]# vim s1.sh
  1. 输入以下内容
#!/bin/bash
echo "Hello World !"  #这是一条语句
  1. 给这个文件赋予执行权限
[root@admin data]# ls
s1.sh
[root@admin data]# chmod +x s1.sh 
[root@admin data]# ls
s1.sh
  1. 执行这个脚本文件

以下4种方式均可。

[root@admin data]# . s1.sh 
Hello World !
[root@admin data]# source s1.sh 
Hello World !
[root@admin data]# ./s1.sh 
Hello World !   
[root@admin data]# bash s1.sh 
Hello World !

2.1.2 Shell 脚本的运行方式

  1. 输入脚本的绝对路径或相对路径

    **注意:**这种情况会新开一个 Shell。

    [root@admin data]# ./s1.sh 
    Hello World !
    [root@admin data]# /opt/data/s1.sh 
    Hello World !
    # 如果取消文件的执行权限,则会出现权限不够
    [root@admin data]# /opt/data/s1.sh 
    -bash: /opt/data/s1.sh: 权限不够
    
  2. bash 或 sh +脚本

    注意: 当脚本没有x权限时,root和文件所有者通过该方式可以正常执行。

    [root@admin data]# bash s1.sh 
    Hello World !
    [root@admin data]# sh s1.sh 
    Hello World !
    
  3. 在脚本的路径前再加". " 或 source

    [root@admin data]# . s1.sh 
    Hello World !
    [root@admin data]# source s1.sh 
    Hello World !
    

三种运行方式的区别

[root@admin data]# name=zhangsan
[root@admin data]# echo $name
zhangsan
[root@admin data]# echo 'echo $name' >> s1.sh 
[root@admin data]# more s1.sh 
#!/bin/bash
echo "Hello World !"  #这是一条语句
echo $name
[root@admin data]# chmod +x s1.sh 
[root@admin data]# ./s1.sh 
Hello World !

[root@admin data]# bash s1.sh 
Hello World !

[root@admin data]# sh s1.sh 
Hello World !

[root@admin data]# . s1.sh 
Hello World !
zhangsan
[root@admin data]# source s1.sh 
Hello World !
zhangsan
[root@admin data]# 

2.1.3 Shell 的分类

  • 操作系统内核(kernel)与shell是独立的套件,而且都可被替换:
  • 不同的操作系统使用不同的shell;
  • 同一个kernel之上可以使用不同的shell。

常见的shell分为两大主流:

  • sh(Linux常用)

    Bourne shell(sh) Solaris,hpux默认shell Bourne again shell(bash) ,Linux系统默认shell

  • csh (Unix常用)

    C shell(csh) tc shell(tcsh)

  • 查看当前系统使用的shell

    [root@admin data]# echo $SHELL
    /bin/bash
    

2.2 Shell 变量

变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数据。脚本语言在定义变量时通常不需要指明类型,直接赋值就可以,Shell 变量也遵循这个规则。

2.2.1 命名规范

  1. 变量名称可以由字母数字下划线组成,但是不能以数字开头**,环境变量名建议大写**,便于区分。

  2. 在 bash 中,变量的默认类型都是字符串型,如果要进行数值运算,则必须指定变量类型为数值型

  3. 变量用等号连接值,等号左右两侧不能有空格

  4. 变量的值如果有空格,需要使用单引号或者双引号包括。

    [root@admin data]# a=1
    [root@admin data]# b=2
    [root@admin data]# c=$a+$b
    [root@admin data]# echo $c
    1+2
    [root@admin data]# d = $a+$b
    -bash: d: 未找到命令
    

2.2.2 变量分类

Linux Shell中的变量分为用户自定义变量,环境变量,位置参数变量和预定义变量。
可以通过set命令查看系统中存在的所有变量

  1. 系统变量:保存和系统操作环境相关的数据。$HOME、$PWD、$SHELL、$USER等等
  2. 位置参数变量:主要用来向脚本中传递参数或数据,变量名不能自定义,变量作用固定。
  3. 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
  4. 自定义变量:用户自定义的变量由字母或下划线开头,由字母,数字或下划线序列组成,并且大小写字母意义不同,变量名长度没有限制。

2.2.3 设置变量

习惯上用大写字母来命名变量。变量名以字母表示的字符开头,不能用数字。

2.2.4 变量调用

在使用变量时,要在变量名前加上前缀$.
使用echo 命令查看变量值。echo $A

2.2.5 变量的赋值

  1. 定义时赋值
    变量=值
    等号两侧不能有空格

    [root@admin test]# AGE=18
    
  2. 将一个命令的执行结果赋给变量

    [root@admin data]# ls
    s1.sh
    [root@admin data]# lsvalue=`ls`
    [root@admin data]# echo $lsvalue
    s1.sh
    

    反引号,运行里面的命令,并把结果返回给变量lsvalue

  3. 将一个变量赋给另一个变量

    [root@admin data]# test=hahaha
    [root@admin data]# echo $test
    hahaha
    [root@admin data]# newtest=lalalatest
    [root@admin data]# echo $newtest
    lalalatest
    [root@admin data]# newtest=lalala$test
    [root@admin data]# echo $newtest
    lalalahahaha
    [root@admin data]# newtest=lalala${test}
    [root@admin data]# echo $newtest
    lalalahahaha
    [root@admin data]# newtest=lalala"$test"
    [root@admin data]# echo $newtest
    lalalahahaha
    

    单引号和双引号的区别:
    现象:单引号里的内容会全部输出,而双引号里的内容会有变化
    原因:单引号会将所有特殊字符脱意

    [root@admin data]# newtest=lalala'$test'
    [root@admin data]# echo $newtest
    lalala$test
    [root@admin data]# newtest=lalala"$test"
    [root@admin data]# echo $newtest
    lalalahahaha
    

2.2.6 删除变量

[root@admin data]# unset newtest
[root@admin data]# echo $newtest

注意: readonly修饰的变量不能删除
用户自定义的变量,作用域为当前的 shell 环境。

[root@admin data]# readonly test=12
[root@admin data]# unset test
-bash: unset: test: 无法反设定: 只读 variable

2.2.7 环境变量

用户自定义变量只在当前的shell中生效,而环境变量会在当前shell和其所有子shell中生效。如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有的shell中生效。
export 变量名=变量值 申明变量
作用域:当前shell以及所有的子shell

[root@admin data]# nn=1
[root@admin data]# export nnn=2
[root@admin data]# echo $nn
1
[root@admin data]# echo $nnn
2
[root@admin data]# bash
[root@admin data]# echo $nn

[root@admin data]# echo $nnn
2

2.2.8 位置参数变量

变量描述
$nn为数字,$0代表命令本身,$1-$9代表第一到第9个参数,十以上的参数需要用大括号包含,如${10}
$*代表命令行中所有的参数,把所有的参数看成一个整体。以$1 $2 … $n的形式输出所有参数
$@代表命令行中的所有参数,把每个参数区分对待。以"$1" "$2" … "$n" 的形式输出所有参数
$#代表命令行中所有参数的个数。添加到 shell 的参数个数
[root@admin data]# vim s2.sh
#添加以下内容
#!/bin/bash
echo '$0='$0
echo "\$1="$1
echo "\$2="$2
echo "\$*="$*
echo "\$@="$@
echo "\$#="$#
[root@admin data]# ./s2.sh 44 55 66
$0=./s2.sh
$1=44
$2=55
$*=44 55 66
$@=44 55 66
$#=3

**$*$@的区别 **
$*$@ 都表示传递给函数或脚本的所有参数,不被双引号" “包含时,都以"$1" "$2" … "$n" 的形式输出所有参数
当它们被双引号” "包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数 。

[root@admin data]# vim s3.sh
#添加以下内容
#!/bin/bash
echo '$0='$0
echo "\$1="$1
echo "\$2="$2
echo "\$*="$*
echo "\$@="$@
echo "\$#="$#
    
echo "这是\$*的结果——不加引号"
for i in $*
 do
  echo $i
 done
    
echo "这是\$@的结果——不加引号"
for i in $@
 do
  echo $i
 done
    
echo "这是\$*的结果——加双引号"
for i in "$*"
 do
  echo $i
 done
    
echo "这是\$@的结果——加双引号"
for i in "$@"
 do
  echo $i
 done

[root@admin data]# chmod +x s3.sh 
[root@admin data]# ./s3.sh 11 22 33 44
$0=./s3.sh
$1=11
$2=22
$*=11 22 33 44
$@=11 22 33 44
$#=4
这是$*的结果——不加引号
11
22
33
44
这是$@的结果——不加引号
11
22
33
44
这是$*的结果——加双引号
11 22 33 44
这是$@的结果——加双引号
11
22
33
44

**shift指令:**参数左移,每执行一次,参数序列顺次左移一个位置,$# 的值减1,用于分别处理每个参数,移出去的参数不再可用

[root@admin data]# vim s4.sh
#添加以下内容
#!/bin/bash
echo '$0='$0
echo "\$1="$1
echo "\$2="$2
echo "\$*="$*
echo "\$@="$@
echo "\$#="$#

shift

echo "\$1="$1
echo "\$#="$#

[root@admin data]# ./s4.sh 1 2 3
$0=./s4.sh
$1=1
$2=2
$*=1 2 3
$@=1 2 3
$#=3
$1=2
$#=2

2.2.9 预定义变量

命令描述
$?执行上一个命令的返回值 执行成功,返回0,执行失败,返回非0(具体数字由命令决定)
$$当前进程的进程号(PID),即当前脚本执行时生成的进程号
$!后台运行的最后一个进程的进程号(PID),最近一个被放入后台执行的进程 &
[root@admin data]# vim s5.sh
#添加以下内容
#!/bin/bash
pwd
echo "\$$="$$
ls /etc > out.log &
echo "\$!="$!
aaaa
echo '$?='$?
pwd
echo '$?='$?
[root@admin data]# chmod +x s5.sh 
[root@admin data]# ./s5.sh 
/opt/data
$$=2039
$!=2040
./s5.sh:行6: aaaa: 未找到命令
$?=127
/opt/data
$?=0

2.2.10 read 指令

read [选项] 值
read -p(提示语句) -n(字符个数) -t(等待时间,单位为秒) –s(隐藏输入)

[root@admin data]# vim s6.sh
#添加以下内容
#!/bin/bash
read -t 10 -p "请输入你的名字" name
echo 'name='$name
[root@admin data]# chmod +x s6.sh 
[root@admin data]# ./s6.sh 
请输入你的名字111
name=111
[root@admin data]# vim s7.sh
#添加以下内容
#!/bin/bash
read -t 10 -sp "请输入你的名字" name
echo 'name='$name
[root@admin data]# chmod +x s7.sh 
[root@admin data]# ./s7.sh 
请输入你的名字name=111
[root@admin data]# vim s8.sh
#添加以下内容
#!/bin/bash
read -t 10 -n 1 -p "请输入你的性别[m,w]" sex
echo 'sex'$sex
[root@admin data]# chmod +x s8.sh 
[root@admin data]# ./s8.sh 
请输入你的性别[m,w]sex=m

2.3 运算符

格式 :expr m + n 或$((m+n)) 注意expr运算符间要有空格
expr命令:对整数型变量进行算术运算

[root@admin data]# n1=1
[root@admin data]# n2=2
[root@admin data]# num=n1+n2
[root@admin data]# echo $num
n1+n2
[root@admin data]# num=`expr $n1 + $n2`
[root@admin data]# echo $num
3
[root@admin data]# num=`expr $n1+$n2`
[root@admin data]# echo $num
1+2
[root@admin data]# num=$(($n1+$n2))
[root@admin data]# echo $num
3
[root@admin data]# num=$(($n1 + $n2))
[root@admin data]# echo $num
3

$()${}的区别

$()的用途和反引号 `一样,用来表示优先执行的命令

${} 就是取变量了

$((运算内容)) 适用于数值运算

2.4 条件测试

2.4.1 内置test命令

内置 test 命令常用操作符号 [] 表示,将表达式写在 [] 中,如下:
[ expression ]
或者:
test expression
注意: expression首尾都有个空格
测试范围:整数、字符串、文件
表达式的结果为真,则test的返回值为0,否则为非0。
当表达式的结果为真时,则变量$?的值就为0,否则为非0

2.4.2 字符串测试

test str1 == str2 测试字符串是否相等
test str1 != str2 测试字符串是否不相等
test str1 测试字符串是否不为空,不为空为true反之为false
test -n str1 测试字符串是否不为空
test -z str1 测试字符串是否为空

[root@admin data]# test "11"=="12";echo $?
0
[root@admin data]# test "11" == "12";echo $?
1
[root@admin data]# test "11" == "11";echo $?
0
[root@admin data]# [ "11" == "12" ];echo $?
1
[root@admin data]# [ "11" == "11" ];echo $?
0
[root@admin data]# ["11" == "11"];echo $?
bash: [11: 未找到命令
127
[root@admin data]# ["11" == "11" ];echo $?
bash: [11: 未找到命令
127
[root@admin data]# [ "11" == "11"];echo $?
bash: [: 缺少 `]'
2
[root@admin data]# test "";echo $?
1
[root@admin data]# test -n "";echo $?
1
[root@admin data]# test -z "";echo $?
0

; 命令连接符号
&& 逻辑与 条件满足,才执行后面的语句
[ -z “KaTeX parse error: Expected 'EOF', got '&' at position 9: name” ] &̲& echo invalid …name" == “yangmi” && echo ok || echo invalid

2.4.3 整数测试

test int1 -eq int2 测试整数是否相等 equals
test int1 -ge int2 测试int1是否>=int2
test int1 -gt int2 测试int1是否>int2
test int1 -le int2 测试int1是否<=int2
test int1 -lt int2 测试int1是否 test int1 -ne int2 测试整数是否不相等

2.4.4 文件测试

test -d file 指定文件是否目录
test –e file 文件是否存在 exists
test -f file 指定文件是否常规文件
test –L File 文件存在并且是一个符号链接
test -r file 指定文件是否可读
test -w file 指定文件是否可写
test -x file 指定文件是否可执行

2.4.5 多重条件测试

条件1 –a 条件2 逻辑与 两个都成立,则为真
条件1 –o 条件2 逻辑或 只要有一个为真,则为真
! 条件 逻辑非 取反

S

2.5 流程控制语句

2.5.1 if

[root@admin data]# vim if.sh
#添加以下内容
#!/bin/bash
read -p "请输出一个名字" name
echo $name

if [ "$name" == root ]
then
 echo "你好,管理员"
elif [ "$name" == linux ];then
 echo "Linux 是我的最爱"
else
 echo "我的名字是"$name
fi
[root@admin data]# chmod +x if.sh 
[root@admin data]# ./if.sh 
请输出一个名字linux
linux
Linux 是我的最爱
[root@admin data]# ./if.sh 
请输出一个名字root
root
你好,管理员
[root@admin data]# ./if.sh 
请输出一个名字zhang
zhang
我的名字是zhang

2.5.2 case

case命令是一个多分支的 if/else 命令,case变量的值用来匹配 value1, value2, value3 等等。匹配到后则执行跟在后面的命令直到遇到双分号为止(;😉 ,case 命令以 esac 作为终止符。

[root@admin data]# vim case.sh
#添加以下内容
#!/bin/bash

case $1 in
 start)
   echo "启动一个程序"
   ;;
 restart)
   echo "重启一个程序"
   ;;
 stop)
   echo "停止一个程序"
   ;;
 *)
   echo "命令有误"
esac
[root@admin data]# chmod +x case.sh 
[root@admin data]# ./case.sh 
命令有误
[root@admin data]# ./case.sh start
启动一个程序
[root@admin data]# ./case.sh stop
停止一个程序
[root@admin data]# ./case.sh restart
重启一个程序

9.5.3 for

[root@admin data]# for i in 1 2 3 4 5;do echo $i;done
1
2
3
4
5
[root@admin data]# for i in {1,2,3,4,5};do echo $i;done
1
2
3
4
5
[root@admin data]# for i in {1..5};do echo $i;done
1
2
3
4
5
[root@admin data]# for i in {2..5};do echo $i;done
2
3
4
5


[root@admin data]# vim for.sh
#添加以下内容
#!/bin/bash
for((i=1;i<10;i+=2))
 do
  echo $i
 done

sum=0
for((i=1;i<=100;i++))
 do
  sum=$(($sum + $i))
 done

echo $sum

[root@admin data]# chmod +x for.sh 
[root@admin data]# ./for.sh 
1
3
5
7
9
5050

9.5.4 while

[root@admin data]# vim while.sh
#添加以下内容
#!/bin/bash
sum=0
i=0
while((i<=100))
 do
  sum=$(($sum + $i))
  i=$(($i + 1))
 done  
echo $sum

sum=0
i=0
 while [ $i -le 100 ]
  do
   sum=$(($sum + $i))
   i=$(($i + 1))
  done  
echo $sum

[root@admin data]# chmod +x while.sh 
[root@admin data]# ./while.sh 
5050
5050

break 命令允许跳出所有循环

continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

2.5.5 函数

函数代表着一个或一组命令的集合,表示一个功能模块,常用于模块化编程。以下是关于函数的一些重要说明:

  • 在 shell 中,函数必须先定义,再调用
  • 使用return value来获取函数的返回值
  • 函数在当前shell中执行,可以使用脚本中的变量。
#!/bin/bash
#无参无返回值
echo "--------------------普通函数--------------------"
function start(){
echo "启动一个程序"
}
stop(){
echo "停止一个程序"
}
echo "-----函数开始执行-----"
start
echo "-----函数执行完毕-----"
#有返回值
echo "--------------------带返回值--------------------"
function sum(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read a
    echo "输入第二个数字: "
    read b
    echo "两个数字分别为 $a$b !"
    return $(($a+$b))
}
sum
echo "输入的两个数字之和为 $? !"

#有参数
echo "--------------------带参数--------------------"
function p(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "第十个参数为 $10 !"
    echo "第十个参数为 ${10} !"
    echo "第十一个参数为 ${11} !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
p 1 2 3 4 5 6 7 8 9 34 73


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值