zoukankan      html  css  js  c++  java
  • linux的shell编程

    1.什么是shell

    命令解释器,将abcd翻译成010101发给内核,让机器看懂,内核处理后,返回101010,shell反编译成dcba呈现给终端,让人看懂。

    2.shell分类

    shell类别 易学性 可移植性 编辑性 快捷性
    Bourne Shell -- sh 容易 较差 较差
    Korn Shell -- ksh 较难 较好 较好
    Bourne Again -- Bash 较好
    POSIX Shell -- psh 较难 较好
    C Shell -- csh 较难 较好 较好
    TC Shell -- tcsh

    linux支持哪几种shell

    centos7

    ubuntu16.04

    3. echo 输出命令

    echo -e 输入转义字符

    root@ubuntu:/etc/network# echo -e "\"
    

    加制表符,需要和-e搭配使用

    root@ubuntu:/etc/network# echo -e "a	b	c"
    a    b    c

    换行,需要和-e搭配使用

    root@ubuntu:/etc/network# echo -e "a	b	c
    d"
    a    b    c
    d

    输出颜色 e[1; 颜色值 abcd e[0m   30m黑色,31m红色,32m绿色,33m黄色,34m青色,37m白色

    脚本执行方法

    root@ubuntu:/home/yanyanzhang/shell_study# cat shell01.sh 
    #!/bin/bash
    
    echo -e "e[1;31m hello world e[0m"

    执行方法一:chmod +x shell01.sh  通过路径执行 ./shell01.sh  

    执行方法二:bash或sh ./shell01.sh 通过命令执行,可以不赋予执行权限

    4.Bash的基本功能

    history  查看历史命令 history-c 清空历史命令文件 history-w 将当次命令强行写入文件中

    输入输出重定向

    例如:将输出在屏幕上的内容输出到文件中

    > 覆盖

    >> 追加,会换行追加

    root@ubuntu:/home/yanyanzhang/shell_study# echo "hello world" > ./shell02.txt 
    root@ubuntu:/home/yanyanzhang/shell_study# cat shell02.txt 
    hello world
    root@ubuntu:/home/yanyanzhang/shell_study# echo "hello world" >> ./shell02.txt 
    root@ubuntu:/home/yanyanzhang/shell_study# cat shell02.txt 
    hello world
    hello world

    xx

    root@ubuntu:/home/yanyanzhang/shell_study# pwd > shell02.txt 
    root@ubuntu:/home/yanyanzhang/shell_study# cat shell02.txt 
    /home/yanyanzhang/shell_study
    root@ubuntu:/home/yanyanzhang/shell_study# pwd >> shell02.txt 
    root@ubuntu:/home/yanyanzhang/shell_study# cat shell02.txt 
    /home/yanyanzhang/shell_study
    /home/yanyanzhang/shell_study

    重定向最典型的应用就是日志

    输入报错信息

    2>> 追加形式,但是怎么知道命令是错误的呢,因此不是很方便

    常用这条命令输出错误和正确信息, 命令 &>> 文件 

    root@ubuntu:/home/yanyanzhang/shell_study# xxxx &>> shell02.txt 
    root@ubuntu:/home/yanyanzhang/shell_study# cat shell02.txt 
    xxxx: command not found
    root@ubuntu:/home/yanyanzhang/shell_study# hostname &>> shell02.txt 
    root@ubuntu:/home/yanyanzhang/shell_study# cat shell02.txt 
    xxxx: command not found
    ubuntu
    root@ubuntu:/home/yanyanzhang/shell_study# 

    还有就是正确和错误分开输出到不同文件,这种更加灵活,正确与错误分开记录。

    root@ubuntu:/home/yanyanzhang/shell_study# ls >> success.txt 2>> error.txt
    root@ubuntu:/home/yanyanzhang/shell_study# ls
    error.txt  shell01.sh  shell02.txt  success.txt
    root@ubuntu:/home/yanyanzhang/shell_study# cat success.txt 
    error.txt
    shell01.sh
    shell02.txt
    success.txt
    root@ubuntu:/home/yanyanzhang/shell_study# cat error.txt 

    多命令执行


    顺序执行:; 间隔

    root@ubuntu:/home/yanyanzhang/shell_study# ls ; pwd
    error.txt  shell01.sh  shell02.txt  success.txt
    /home/yanyanzhang/shell_study
    root@ubuntu:/home/yanyanzhang/shell_study# 

    前面正确执行后面才会执行 &&

    root@ubuntu:/home/yanyanzhang/shell_study# ls && echo "success"
    error.txt  shell01.sh  shell02.txt  success.txt
    success
    root@ubuntu:/home/yanyanzhang/shell_study# xxx && echo "success"
    No command 'xxx' found, did you mean:
     Command 'xxd' from package 'vim-common' (main)
     Command 'x2x' from package 'x2x' (universe)
     Command 'xdx' from package 'xdx' (universe)
     Command 'xx' from package 'fex-utils' (universe)
    xxx: command not found
    root@ubuntu:/home/yanyanzhang/shell_study# 

    前面报错后面执行,前面正确后面不执行 ||

    root@ubuntu:/home/yanyanzhang/shell_study# sssss || echo "ffff"
    sssss: command not found
    ffff
    root@ubuntu:/home/yanyanzhang/shell_study# ls || echo "ffff"
    error.txt  shell01.sh  shell02.txt  success.txt

    && 和 || 组合使用,可以知道命令是否正确执行,必须先&& 后 ||

    root@ubuntu:/home/yanyanzhang/shell_study# ls && echo "sucess" || echo "fail"
    error.txt  shell01.sh  shell02.txt  success.txt
    sucess
    root@ubuntu:/home/yanyanzhang/shell_study# lsssss && echo "sucess" || echo "fail"
    lsssss: command not found
    fail
    其实可以单分支取代if

    管道符

    行提取命令:grep

    过滤 grep xxx /xx/xx/test.txt 从test.txt中过滤出xxx后输出

    root@ubuntu:/home/yanyanzhang/Desktop# grep a ./haha.py 
    print("haha")

    -A 3 将匹配的内容后3行也输出

    root@ubuntu:/home/yanyanzhang/Desktop/docker_flask/flask_demo# grep -A 3  app ./start.py 
    app = Flask(__name__)
    
    
    @app.route("/")
    def index():
        return jsonify({"message":"hello flaski"})
    
    --
        app.run(port=5001)

    -n 输出行号

    root@ubuntu:/home/yanyanzhang/Desktop/docker_flask/flask_demo# grep -n  app ./start.py 
    3:app = Flask(__name__)
    6:@app.route("/")
    14:    app.run(port=5001)

    -c 找到复合条件字符串的个数

    root@ubuntu:/home/yanyanzhang/Desktop/docker_flask/flask_demo# grep -c app ./start.py 
    3

    grep和管道符| 配合使用

    root@ubuntu:/home/yanyanzhang/Desktop/docker_flask/flask_demo# netstat -an | grep 80
    tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN     
    unix  3      [ ]         STREAM     CONNECTED     31680    
    unix  3      [ ]         STREAM     CONNECTED     33280    
    unix  3      [ ]         STREAM     CONNECTED     36080    
    unix  3      [ ]         STREAM     CONNECTED     33180    /run/systemd/journal/stdout
    unix  3      [ ]         STREAM     CONNECTED     28032    
    unix  3      [ ]         STREAM     CONNECTED     32803    
    unix  2      [ ]         DGRAM                    60580    

    通配符

    . * ? [] 

    其他特殊符号

    单引号 ''  :所有的特殊符号都没有含义,如$,`等都没有含义。

    双引号 "" :所有的特殊符号都没有含义,除了 $, `,例外,$调用变量值,`引用命令,转义符

    反引号 `` :反引号包括起来的是系统命令,在Bash中会先去执行它,和$()作用一样,不过推荐使用$(),因为反引容易看错。

    $():和反引号一样,用来引用系统命令

    root@ubuntu:/home# a=$(date)  #先在子shell执行date,然后将结果赋值给a
    root@ubuntu:/home# echo $a # 获取a的值
    Mon May 3 14:19:20 CST 2021

     应用一: 获取执行脚本的位置,并将目录赋值给变量

    #! /bin/bash
    basedir=$(cd $(dirname $0) && echo $(pwd))
    echo $basedir

    #dirname的用法
    direname /usr/bin 输出 /usr 返回给定路径的上层路径

      root@cloud:/usr/lib/python2.7/dist-packages/ics# dirname "$0"  # 返回 . 表示当前路径
      .

    ():用于一串命令执行,()中的命令会在子shell中运行

    root@ubuntu:/home# name="zhangsan"
    root@ubuntu:/home# (name="lisi";echo $name)  # echo $name 输出的是子shell的变量值,之后子shell就关闭消失了
    lisi
    root@ubuntu:/home# echo $name # 输出的是当前shell的变量值,且值没有发生更改
    zhangsan

    {}:用于一串命令执行时候,{}的命令会在当前shell中执行,也可用于变量变形和替换

    root@ubuntu:/home# name="zhangsan"
    root@ubuntu:/home# { name="lisi";echo $name; }
    lisi
    root@ubuntu:/home# echo $name
    lisi

    []:用于变量的测试,后面单独说明

    #:注释

    $:调用变量的值。

    :转义。

    5.bash常用快捷键

    快捷键 作用
    CTRL + A 光标从任意位置移到命令开头
    CTRL + E 光标从任意位置移到命令结尾
    CTRL + L 清屏 = clear
    CTRL + U 删除或剪切光标之前的命令,不用使用退格键一个一个删除
    CTRL + K 删除或剪切光标之后的命令。
    CTRL + Y 粘贴ctrl+u和ctrl+K剪切的内容
    CTRL + R 历史命令中搜索
    CTRL + C 终止当前命令

    6.bash的变量和运算规则

    1.shell变量默认类型是字符串,如果要进行数值运算,需要指定变量类型为数值型。
    2.变量命名规则和其他语言一样
    3.变量命名=左右两边不能加空格
    5.变量里面有空格,双引号阔起来
    6.变量的默认值拼接
    root@ubuntu:/home# test=123
    root@ubuntu:/home# test="$test"456  # 另外一种写法 test=${test}456也行
    root@ubuntu:/home# echo $test
    123456

    7.bash变量的分类

    变量分类 说明
    用户自定义变量 用户定义
    环境变量 系统定义,用来保存系统操作环境的数据,系统变量的变量名可以自由定义,但是一般对系统起作用的环境变量的变量名是系统预先设定好的
    位置参数变量 脚本传递,,变量名不能自定义,变量作用也是固定的
    预定义变量 Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的

    用户自定义变量

    root@ubuntu:/home# name=zhang  # 因为shell默认变量都是字符串类型,因此可以不用向其他语言一样需要加引号
    root@ubuntu:/home# age="10"
    root@ubuntu:/home# echo $name; echo $age # 调用变量必须加$
    zhang
    10

    变量不存在和变量值为空,是两个概念

    root@ubuntu:/home# name=""
    root@ubuntu:/home# echo $name
    
    root@ubuntu:/home# echo $school
    
    root@ubuntu:/home# 
    # 但是输出的样子很像,怎么做区别呢?

    查看变量

    set -u 设定此选项,调用未声明变量会报错。

    root@ubuntu:/home# set -u   # 临时生效,重启就没了,长久生效,需要加入环境变量
    root@ubuntu:/home# echo $name
    
    root@ubuntu:/home# echo $school
    bash: school: unbound variable

         -x 设定此选项,命令执行前,先把命令输出一次,set +x 取消这个设置

    root@ubuntu:/home# echo $name
    + echo
    
    root@ubuntu:/home# 

    set 查看环境变量---不全,能看到自定义变量,

    env 查询环境变量---不全,看不到自定义变量

    删除变量

    unset 变量名

    root@ubuntu:/home# age=100
    + age=100
    root@ubuntu:/home# echo $age
    + echo 100
    100
    root@ubuntu:/home# unset age
    + unset age
    root@ubuntu:/home# echo #age
    + echo

    环境变量

    用户自定义环境变量:只在当前shell生效,子shell中并不生效

    export AGE = "18"

    root@ubuntu:/home# export AGE="18"
    + export AGE=18
    + AGE=18
    root@ubuntu:/home# echo $AGE
    + echo 18
    18

    env 查看,ubuntu16.04中set查看命令无效,只能env查看,centos7中set和env都有效

    系统自带的环境变量

    PATH环境变量:系统查看命令的路径

    ubantu16.04的PATH

    PATH=/root/.pyenv/shims:/root/.pyenv/bin:/root/.pyenv/shims:/root/.pyenv/bin:/root/.pyenv/shims:/root/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

     centos7的PATH

    ls 执行后,系统先去PATH定义的路径路径里面查找ls,找到就指定,找不到就报错,/bin,有ls

    root@ubuntu:/bin# lslls
    lslls: command not found  # 在$PATH指定的路径下没找到

    需求:如何让我们定义的hello.sh直接运行而不用指定路径 ./xxxx/xxx/hello.sh

    方法一:加入

    root@ubuntu:/home/yanyanzhang/shell_study# ls
    error.txt  hello.sh  shell01.sh  shell02.txt  success.txt
    root@ubuntu:/home/yanyanzhang/shell_study# cp ./hello.sh /bin/
    root@ubuntu:/home/yanyanzhang/shell_study# ls
    error.txt  hello.sh  shell01.sh  shell02.txt  success.txt
    root@ubuntu:/home/yanyanzhang/shell_study# hello.sh
    hello world

      root@ubuntu:/home/yanyanzhang/shell_study# rm -rf /bin/hello.sh
      root@ubuntu:/home/yanyanzhang/shell_study# hello.sh
      bash: /bin/hello.sh: No such file or directory

    方法二:搜索路径叠加

    root@ubuntu:/home/yanyanzhang/shell_study/sh# PATH="$PATH":/home/yanyanzhang/shell_study/sh
    root@ubuntu:/home/yanyanzhang/shell_study/sh# hello.sh 
    hello world
    root@ubuntu:/home/yanyanzhang/shell_study/sh# echo $PATH
    /root/.pyenv/shims:/root/.pyenv/bin:/root/.pyenv/shims:/root/.pyenv/bin:/root/.pyenv/shims:/root/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/yanyanzhang/shell_study/sh

    PS1环境变量:提示符

    root@ubuntu:/home/yanyanzhang/shell_study/sh# echo $PS1
    [e]0;u@h: wa]${debian_chroot:+($debian_chroot)}u@h:w$

    中文输出问题

    1.安装中文字体和编码
    2.操作终端支持中文显示和中文编码
    root@ubuntu:/home/yanyanzhang/shell_study/sh# echo $LANG
    en_US.UTF-8  #不支持中文

    要支持中文,需要下载中文插件,还需要修改 /etc/sysconfig/il8n    LANG="zh_CNN.UTF-8"

    位置参数变量:传参

    位置参数变量 作用
    $n n为数字,$0表示命令本身,$1-9表示第一个到第九个参数,十个以上需要用大括号${}
    $* 表示命令行中的所有参数,$*将参数看做为一个整体
    $@ 表示命令行中的所有参数,不过$@把每个参数分开对待
    $# 表示命令行中所有参数的个数

    练习一: 输入 count.sh 100 200 屏幕输出300 

    #! /bin/bash
    
    #$0 代表命令本身
    # args1  接收第一个位置参数
    a=$1
    # args2  接收第二个位置参数
    b=$2
    # must use double () for int plus int,必须使用$(()),shell才知道要做int形式的加法,而不是拼接字符串
    sum=$((a+b))
    echo $sum
    
    
    ######
    root@ubuntu:/home/yanyanzhang/shell_study# ./count.sh 100 200
    300

    练习二:将传递的参数输出出来

    #! /bin/bash
    
    # echo 和"中间需要空一格格子,后面的当做参数,否则都当做命令了,command is not found
    echo "$* is $*"
    echo "$@ is $@"
    echo "$# is $#"
    
    
    #######
    root@ubuntu:/home/yanyanzhang/shell_study# ./test01.sh 11 22 33 44 55
    $* is 11 22 33 44 55
    $@ is 11 22 33 44 55
    $# is 5

    练习三:

    #! /bin/bash
    
    for i in 1 2 3 4
    
        do
            echo $i
        done
    
    ###
    root@ubuntu:/home/yanyanzhang/shell_study# ./for.sh 
    1
    2
    3
    4

    通过循环查看$*和$@的区别

    #! /bin/bash
    
    for i in "$*"   # 将11 22 33 看成一整体字符串 "11 22 33"
    
        do
            echo $i
        done
    
    echo "+++++++++++++++++++++++++++++++++++"
    
    for y in "$@" # 将11 22 33 看成单独的个体字符串 "11" "22" "33"
    
        do
            echo $y
        done
    
    #########
    root@ubuntu:/home/yanyanzhang/shell_study# ./for_2.sh 11 22 33
    11 22 33
    +++++++++++++++++++++++++++++++++++
    11
    22
    33

    预定义变量

    $?:保存上一条命令的返回状态,0代表上一条命令正确执行,非0表示错误执行

    root@ubuntu:/home/yanyanzhang/shell_study# ls
    count.sh  error.txt  for_2.sh  for.sh  hello.sh  sh  shell01.sh  shell02.txt  success.txt  test01.sh
    root@ubuntu:/home/yanyanzhang/shell_study# echo $?
    0
    root@ubuntu:/home/yanyanzhang/shell_study# lsll
    lsll: command not found
    root@ubuntu:/home/yanyanzhang/shell_study# echo $?
    127

    场景:linux下确定nginx是否在运行

    1. 查看Pid的方式
    
    root@ubuntu:/home/yanyanzhang/shell_study# ps -C bash -o pid
       PID
      2773
     15655
     25439
    root@ubuntu:/home/yanyanzhang/shell_study# ps -C nginx -o pid
       PID
    
    2. 查看端口的方式
    
    lsof -i:80 

    结合 $? 来判断 nginx是否在运行

    root@ubuntu:/home/yanyanzhang/shell_study# ps -C nginx -o pid
       PID
    root@ubuntu:/home/yanyanzhang/shell_study# echo $?
    1
    root@ubuntu:/home/yanyanzhang/shell_study# ps -C bash -o pid
       PID
      2773
     15655
     25439
    root@ubuntu:/home/yanyanzhang/shell_study# echo $?
    0

    # 改成shell代码为

    root@ubuntu:/home/yanyanzhang/shell_study# ps -C nginx -o pid || echo "nginx no running"   前错后执行
    PID
    nginx no running
    root@ubuntu:/home/yanyanzhang/shell_study# ps -C nginx -o pid && echo "nginx running"  前对后执行
    PID

    逻辑与 && 逻辑或 || 的原理就是 $?, 通过$?的值决定后面是否执行

    $$:返回当前进程的pid号

    root@ubuntu:/home/yanyanzhang/shell_study# cd ..
    root@ubuntu:/home/yanyanzhang# echo $$
    25439
    root@ubuntu:/home/yanyanzhang# ps -ef|grep bash
    yanyanz+   2773   2766  0 01:36 pts/11   00:00:00 bash
    root      15655  15654  0 02:01 pts/11   00:00:00 bash
    root      25439  15655  0 05:22 pts/11   00:00:00 bash
    root      44722  25439  0 14:17 pts/11   00:00:00 grep --color=auto bash

    $!:后台运行的最后一个进程的pid号

    # ubuntu不认
    root@ubuntu:/home/yanyanzhang# echo $!
    bash: $!: unbound variable
    
    # centos认
    [root@macbook ~]# echo $! #什么都不显示

    8. read接收键盘输入

    -p 提示信息,告诉输入者

    -t 等待秒数

    -n  字符数

    -s 隐藏输入的数据,用于机密信息输入

    练习一:带输入提示和等待时间的脚本

    #! /bin/bash
    
    read -t 30 -p "please input num1: " num1
    echo "num1 is $num1"
    read -t 30 -p "please input num2: " num2
    echo "num2 is $num2"
    
    sum=$(( $num1 + $num2  ))
    
    echo "result is $sum"
    
    ######################
    root@ubuntu:/home/yanyanzhang/shell_study# /bin/bash ./count2.sh 
    please input num1: 19
    num1 is 19
    please input num2: 23
    num2 is 23
    result is 42

    相比位置参数,read面向的是脚本的使用者,位置参数 面向的是脚本的书写者。

    9.shell运算

    shell将所有的变量都默认是字符串类型,不便做数值运算。因此出现declare
    
    declare      -    给变量设定类型
                 +    取消变量的类型属性
                -a    将变量声明为数组型
                -i    将变量声明为整型
                -r    将变量声明为只读变量。
                -x    将变量声明为环境变量
                -p    显示指定变量的声明类型

    数组赋值

    # 标准赋值
    root@ubuntu:/home/yanyanzhang/shell_study# declare -a name[0]=1
    root@ubuntu:/home/yanyanzhang/shell_study# declare -a name[1]=2
    root@ubuntu:/home/yanyanzhang/shell_study# echo ${name[*]}
    1 2
    root@ubuntu:/home/yanyanzhang/shell_study# echo ${name[0]}
    1
    root@ubuntu:/home/yanyanzhang/shell_study# echo ${name[1]}
    2
    
    
    # 简洁赋值
    root@ubuntu:/home/yanyanzhang/shell_study# age[0]=1
    root@ubuntu:/home/yanyanzhang/shell_study# age[1]=3
    root@ubuntu:/home/yanyanzhang/shell_study# echo ${age[*]}
    1 3

    declear -x test="123" 将变量test变成环境变量,export test 的实现也是用declare -x  test 的形式实现的,为了方便,用export代替。

    declare -p 查看所有

    root@ubuntu:/home/yanyanzhang/shell_study# declare -p
    declare -x AGE="18"
    declare -- BASH="/bin/bash"
    declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath"
    declare -ir BASHPID
    declare -A BASH_ALIASES='()'
    declare -a BASH_ARGC='()'
    declare -a BASH_ARGV='()'
    declare -A BASH_CMDS='()'
    declare -- BASH_COMMAND
    declare -a BASH_LINENO='()'
    declare -a BASH_SOURCE='()'
    declare -- BASH_SUBSHELL
    declare -ar BASH_VERSINFO='([0]="4" [1]="3" [2]="48" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")'
    declare -- BASH_VERSION="4.3.48(1)-release"
    declare -x CLUTTER_IM_MODULE="xim"
    declare -- COLUMNS="160"
    declare -x COMPIZ_BIN_PATH="/usr/bin/"
    declare -x COMPIZ_CONFIG_PROFILE="ubuntu"
    declare -- COMP_WORDBREAKS

    查看指定

    root@ubuntu:/home/yanyanzhang/shell_study# declare -p AGE
    declare -- AGE="18"
    root@ubuntu:/home/yanyanzhang/shell_study# declare -p age
    declare -a age='([0]="1" [1]="3")'

    expr和let加法运算

    # 这种写法不推荐
    root@ubuntu:/home/yanyanzhang/shell_study# a=11
    root@ubuntu:/home/yanyanzhang/shell_study# b=22
    root@ubuntu:/home/yanyanzhang/shell_study# declare -i c=$a+$b
    root@ubuntu:/home/yanyanzhang/shell_study# echo $c
    33
    
    # $a和$b和+之间必须有空格,这种写法不推荐
    root@ubuntu:/home/yanyanzhang/shell_study# d=$(expr $a + $b)
    root@ubuntu:/home/yanyanzhang/shell_study# echo $d
    33

    # 这种方法也不推荐

     root@ubuntu:/home/yanyanzhang/shell_study# let e=$a+$b
     root@ubuntu:/home/yanyanzhang/shell_study# echo $e
     33

    推荐的做法:

    root@ubuntu:/home/yanyanzhang/shell_study# a=11
    root@ubuntu:/home/yanyanzhang/shell_study# b=22
    root@ubuntu:/home/yanyanzhang/shell_study# c=$(($a+$b))
    root@ubuntu:/home/yanyanzhang/shell_study# echo $c
    33

    练习:shell写一个加减乘除的计算器

    #! /bin/sh
    
    # 没有判断 num1和num2的类型等问题,后面会改进
    read -t 20 -p "please input one num1: " num1 echo "$num1" read -t 20 -n1 -p "please input one operator like [+,-,*,/]: " operator echo "$operator" read -t 20 -p "please input two num2: " num2 echo "$num2" declare -i num1 declare -i num2 [ "$operator" == "+" ] && echo "ret is $(($num1 + $num2))" [ "$operator" == "-" ] && echo "ret is $(($num1 - $num2))" [ "$operator" == "*" ] && echo "ret is $(($num1 * $num2))" [ "$operator" == "/" ] && [ "$num2" != 0 ] && echo "ret is $(($num1 / $num2))"

    10. 变量测试及内容置换

    变量置换方式 变量y没有定义 变量y值为空 变量y有值
    x=${y-新值} x=新值 x为空 x=$y
    x=${y:-新值} x=新值 x=新值 x=$y
    x=${y+新值} x为空 x=新值 x=新值
    x=${y:+新值} x为空 x=新值 x=新值
    x=${y=新值} x=新值
    y=新值

    x为空
    y不变

    x=$y
    y不变
    x=${y:=新值} x=新值
    y=新值
    x=新值
    y=新值
    x=$y
    y不变
    x=${y?新值} 新值输出到标准错误
    输出(屏幕)
    x为空 x=$y
    x=${y:?新值} 新值输出到标准错误
    输出(屏幕)
    新值输出到标准错误
    输出(屏幕)
    x=$y

    为什么需要这个,原因是,怎么判断这个变量存在,还是这个变量为空,下面的方法通过set -u,不存在就报错形式可以判断,但比较麻烦。通过间接x来判断y,不存在还是为空

    root@ubuntu:/home/yanyanzhang/shell_study# echo $aa
    
    root@ubuntu:/home/yanyanzhang/shell_study# aa=""
    root@ubuntu:/home/yanyanzhang/shell_study# echo $aa
    
    root@ubuntu:/home/yanyanzhang/shell_study# set -u
    root@ubuntu:/home/yanyanzhang/shell_study# echo $aa
    
    root@ubuntu:/home/yanyanzhang/shell_study# echo $bb
    bash: bb: unbound variable

    测试

    # aaa和bbb都没有定义
    root@ubuntu:/home/yanyanzhang/shell_study# aaa=${bbb-100} root@ubuntu:/home/yanyanzhang/shell_study# echo $aaa 100 # 推断出bbb没有定义

    11. 环境变量配置文件

    source 配置文件:加载配置文件,使其生效,否则需要重新登陆,才生效。

    . 配置文件:加载配置文件,使其生效

    linux系统登陆时,主要生效的配置文件有五个

    /etc/profile  : 对所有用户生效,root及非root用户,
    
    /etc/profile.d/*.sh: 对所有用户生效,root及非root用户
    ~/.bash_profile :只对当前用户生效

    ~/.bashrc :只对当前用户生效

    /etc.bashrc : 对所有用户生效,root及非root用户

    执行顺序:红色为登陆下的读取和加载顺序,蓝色为非登陆下的加载顺序,例如su,例如 bash bash等命令。 

    下图是基于centos6的流程图:

    centos7的流程图:

    (1)/etc/profile : 此文件为系统的每个用户设置系统环境信息,当用户登录时该文件被执行。
    
    (2)~/.bash_profile(或.profile) : 每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件。
    
    (3)~/.bashrc : 该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该该文件被读取。
    
    (4)/etc/bashrc : 为每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取.

    ubuntu16.04的流程

    ubuntu16.04默认只有四个环境变量:
    
    /etc/profile:此文件为系统的每个用户设置环境信息,对/etc/profile有修改的话必须得重启你的修改才会生效,此修改对每个用户都生效。可以通过命令
    source /etc/profile立即生效
    
    /etc/bash.bashrc:为每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取.如果你想对所有的使用bash的用户修改某个配置并在以后打开的bash都生效的话可以修改这个文件,
     修改这个文件不用重启,重新打开一个bash即可生效。
    
    ~/.bashrc:该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件被读取
    
    ~/.profile:每个用户都可使用该文件输入专用于当前用户使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件.
    
     此文件类似于/etc/profile,也是需要需要重启才会生效,/etc/profile对所有用户生效,~/.bash_profile只对当前用户生效。
    
    
    # 区别
    
    /etc/bash.bashrc对所有用户新打开的bash都生效, 项目中的Ubuntu修改了这个文件,增加了读取xxxx文件,实现了cdlog和cdcode的快速跳转
     ~/.bashrc只对当前用户新打开的bash生效。

    命令提示符如果 -bash#,说明删除了环境变量配置文件

    退出登陆会调用: ~/.bash_logout

    历史命令保存文件: ~/.bash_history

    自定义登陆提示信息

    ubuntu16.04修改位置为

    root@ubuntu:/etc/update-motd.d# ls
    00-header  10-help-text  50-motd-news  90-updates-available  91-release-upgrade  92-unattended-upgrades  98-fsck-at-reboot  98-reboot-required  99-esm
    root@ubuntu:/etc/update-motd.d# pwd
    /etc/update-motd.d

    内容

    #!/bin/bash
    
    printf "==================================================="
    printf "welcome to my planet my old baby"
    printf "==================================================="

    执行效果

    root@ubuntu:/etc/update-motd.d# run-parts /etc/update-motd.d/
    Welcome to Ubuntu 16.04.7 LTS (GNU/Linux 4.15.0-133-generic x86_64)
    
     * Documentation:  https://help.ubuntu.com
     * Management:     https://landscape.canonical.com
     * Support:        https://ubuntu.com/advantage
    
     * Pure upstream Kubernetes 1.21, smallest, simplest cluster ops!
    
         https://microk8s.io/
    ===================================================welcome to my planet my old baby===================================================
    109 packages can be updated.
    64 updates are security updates.
    
    New release '18.04.5 LTS' available.
    Run 'do-release-upgrade' to upgrade to it.
    
    root@ubuntu:/etc/update-motd.d# 

    自定义快捷键:项目中cdcode直接进入code文件夹,cdlog直接进入log文件夹

    stty -a 查看所有的快捷键

    root@ubuntu:/home/yanyanzhang# stty -a
    speed 38400 baud; rows 51; columns 160; line = 0;
    intr = ^C; quit = ^; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
    lnext = ^V; discard = ^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 -flusho -extproc

    需求:定义一个快捷键,cdcode 直接进入 /home/yanyanzhang/code文件夹下。 

    # 1. 编写一个cdcode脚本
    root@ubuntu:/home/yanyanzhang/shell_study# cat cdcode.sh 
    #! /bin/bash
    
    cd /home/yanyanzhang/code
    
    # 2. 直接执行脚本
    ./cdcode.sh 不会跳转,只有source ./cdcode.sh才会跳转。source不会创建子shell,而是在当前shell环境下执行
    
    # 3. 给source ./cdcode.sh这条命令起一个别名,cdcode
    在/root/.bashrc最后一句加上
    # zhang edit 20210504
    alias cdcode="source /home/yanyanzhang/shell_study/cdcode.sh"

    #########

    root@ubuntu:/home/yanyanzhang/shell_study# cd /
    root@ubuntu:/# cdcode
    root@ubuntu:/home/yanyanzhang/code#

    使用source的原因是:

    1. 在shell在执行脚本的时候,会创建一个子shell,并在子shell中逐条执行脚本中的指令
    
    2. 子shell会从父shell中继承了环境变量,但是执行后不会改变父shell的环境变量
    
    3. 在子shell中的操作和环境变量不会影响父进程,在执行完shell后又回到了父进程

    12.正则 

    .   匹配换行符外任意字符
    *  匹配0次或多次
    ?  
    ^  开头
    $   结尾

    练习一: grep "a*" 就是列出所有内容, *代表0或任意个

    过滤包含a的行,至少包含一个a,"aa*"

     grep :行匹配

    -s: 非递归查找
    -r:  递归查找

    练习一:查找linux下包含 cdlog字符串的文件夹及路径

    root@cloud:/# grep -r "cdlog" /*
    /etc/ics/alias_common:alias cdlog='cd /var/log/ics'
    grep: /etc/ics/docker.sock: No such device or address
    ^C

     练习二:查找指定目录/etc下包含mysql字符串的文件及路径

    root@cloud:/# grep -s mysql /etc/*
    /etc/services:mysql             3306/tcp
    /etc/services:mysql             3306/udp
    /etc/services:mysql-proxy       6446/tcp                        # MySQL Proxy
    /etc/services:mysql-proxy       6446/udp

     grep -v 取反

    root@cloud:/# grep -v log /etc/ics/alias_common # 不包含
    
    alias shortcmd='cat /etc/bash.bashrc|grep "^alias" |grep -v "alias shortcmd="|sed "s/^alias //g"'
    alias cd..='cd ..'
    alias ..='cd ..'
    alias cd...='cd ../..'
    alias ...='cd ../..'
    alias cd-='cd -'
    alias ll='ls -l --color=auto'
    alias cdetc='cd /etc/ics'
    alias cddb='cd /var/lib/ics/db/'
    alias cdcode='cd /usr/lib/python2.7/dist-packages/ics/'
    alias cdvhost='cd /var/lib/ics/vhost/'
    alias cdimg='cd /var/lib/ics/vhost/images'
    alias cddesk='cd /var/lib/ics/vhost/instances/'
    alias cdins='cd /var/lib/ics/vhost/install_src/'
    alias cdbin='cd /usr/local/bin/'
    alias cdsys='cd /lib/systemd/system/'
    alias cdclouddisk='cd /var/lib/ics/vhost/clouddisk/'
    alias cdservice='cd /lib/systemd/system/'
    alias cdidesk='cd /var/lib/ics/vhost/iSingleSphere/images/'
    alias rootssh="sed -i 's/^s*#*s*PermitRootLogins.*$/PermitRootLogin yes/g' /etc/ssh/sshd_config; service ssh restart"
    alias offrootssh="sed -i 's/^s*#*s*PermitRootLogins.*$/PermitRootLogin prohibit-password/g' /etc/ssh/sshd_config; service ssh restart"

    grep -n 显示行号

    root@iZwz9434lxf5ptexiu13giZ:/etc# grep if ./bash.bashrc -n
    9:# check the window size after each command and, if necessary,
    13:# set variable identifying the chroot you work in (used in the prompt below)
    14:if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    32:#if ! shopt -oq posix; then
    33:#  if [ -f /usr/share/bash-completion/bash_completion ]; then
    35:#  elif [ -f /etc/bash_completion ]; then
    41:if [ ! -e "$HOME/.sudo_as_admin_successful" ] && [ ! -e "$HOME/.hushlogin" ] ; then
    43:    if [ -x /usr/bin/sudo ]; then
    53:# if the command-not-found package is installed, use it
    54:if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then
    57:                if [ -x /usr/lib/command-not-found ]; then
    60:                elif [ -x /usr/share/command-not-found/command-not-found ]; then

    cut:列匹配

    root@iZwz9434lxf5ptexiu13giZ:~# who
    root     pts/0        2021-05-06 10:55 (117.36.118.125)
    root     pts/1        2021-05-06 10:55 (117.36.118.125)
    
    # 提取每行的时间
    
    # -c 按照位数提取。
    root@iZwz9434lxf5ptexiu13giZ:~# who|cut -c 15-39
            2021-05-06 10:55 
            2021-05-06 10:55 
    
    # 带格式查看,notepadd++按照格式,则位数正确 15-39

    -d -f 搭配使用 -d 指定按照什么切割,-f选择切割后的区域 root@iZwz9434lxf5ptexiu13giZ:~# who root pts/0 2021-05-06 10:55 (117.36.118.125) root pts/1 2021-05-06 10:55 (117.36.118.125) root@iZwz9434lxf5ptexiu13giZ:~# who|cut -d "(" -f1 root pts/0 2021-05-06 10:55 root pts/1 2021-05-06 10:55 root@iZwz9434lxf5ptexiu13giZ:~# who|cut -d "(" -f2 117.36.118.125) 117.36.118.125)

    awk

    awk是一个强大的文本分析工具,简单来说awk就是把文件逐行读入,(空格,制表符)为默认分隔符将每行切片,切开的部分再进行各种分析处理
    
    awk [-F field-separator] 'commands' input-file(s)

    -F 指定分隔符,以:为分隔符,输出分割后的第一和第二列

    root@iZwz9434lxf5ptexiu13giZ:/etc# awk -F : '{print $1,$2}'  /etc/passwd 
    root x
    daemon x
    bin x
    sys x
    sync x
    games x
    man x
    lp x

      

     install 命令

    install -p -d -o root -g root  -m  755 ${DIR_DEBIAN}
    install -p -d -o root -g root  -m  755 ${DIR_BUILD}/lib/systemd/system
    install -p -d -o root -g root  -m  755 ${DIR_BUILD}/usr/bin
    install -p -d -o root -g root  -m  755 ${DIR_PYTHON}

     用 install命令去完成需要 cpchmodchown等一系列命令才能完成的操作。

    -o : 指定owner 为 root

    -g:  指定group 为 root

    -d:  创建目录

    -p:保存,时间为访问时间

    -m:指定文件权限

    说明:install和cp功能很像,但是在拷贝的过程中可以修改文件访问属性,组属性等其他操作,一般用于Makefile。

    练习一:不存在创建目录,并修改权限

    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/shell_study# install -p -d -o root -g root -m 755 ~/yanyan/tmp/test     # test文件本来不存在 -d 创建出来的
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/shell_study# ls
    input_args.sh  shell_var  test1.sh  test2.sh  test3.sh  test4.sh
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/shell_study# cd ~/yanyan/tmp/test/
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test# cd ..
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp# ll -rt
    total 12
    drwxr-xr-x 5 root root 4096 May  6 15:47 ../
    drwxr-xr-x 2 root root 4096 May  6 15:48 test/  # -m 修改了权限 -p 修改了创建时间 -g指定了所属组,-o制定了所属人
    drwxr-xr-x 3 root root 4096 May  6 15:48 ./

    练习二:存在的文件复制到指定目录

    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test# install -p -o root -g root -m 755  ~/yanyan/tmp/test/dragon.txt  ~/yanyan/tmp/test_two
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test# cd ../test_two/
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test_two# ls
    dragon.txt
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test_two# ll -rt
    total 8
    drwxr-xr-x 4 root root 4096 May  6 15:57 ../
    -rwxr-xr-x 1 root root    0 May  6 16:14 dragon.txt*
    drwxr-xr-x 2 root root 4096 May  6 16:14 ./

    cat 命令

    cat <<EOF>> xxx.txt  将输入EOF之前的内容写入到 xxx,.txt中, cat <<EOF 输入EOF停止 >> 重定向

    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test_two# cat <<EOF>> ~/yanyan/tmp/test_two/dragon.txt 
    > nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
    > sdfasfaewf
    > sdfasfsdfsdfasfasfasfasfas
    > sfasfasfsfasdf
    > EOF
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test_two# cat dragon.txt 
    faewsfafsfsfafe # 原来
    nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn # 下面都是新写入
    sdfasfaewf
    sdfasfsdfsdfasfasfasfasfas
    sfasfasfsfasdf
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test_two# 

    权限说明

    具体的权限是由数字来表示的,读取的权限等于4,用r表示;写入的权限等于2,用w表示;执行的权限等于1,用x表示;
    通过4、2、1的组合,得到以下几种权限:0(没有权限);4(读取权限);5(4+1 | 读取+执行);6(4+2 | 读取+写入);7(4+2+1 | 读取+写入+执行)
    以755为例:
    1-3位7等于4+2+1,rwx,所有者具有读取、写入、执行权限;
    4-6位5等于4+1+0,r-x,同组用户具有读取、执行权限但没有写入权限;
    7-9位5,同上,也是r-x,其他用户具有读取、执行权限但没有写入权限。

    chown 文件切换所属用户

    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test# chown -R xiaoming ./dragon.txt 
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test# ll -rt
    total 8
    drwxr-xr-x 4 root     root 4096 May  6 15:57 ../
    -rw-r--r-- 1 xiaoming root    0 May  6 16:14 dragon.txt
    drwxr-xr-x 2 root     root 4096 May  6 16:14 ./

    chgrp 文件切换所属组

    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test# chgrp -R xiaoming ./dragon.txt 
    root@iZwz9434lxf5ptexiu13giZ:~/yanyan/tmp/test# ll -rt
    total 8
    drwxr-xr-x 4 root     root     4096 May  6 15:57 ../
    -rw-r--r-- 1 xiaoming xiaoming    0 May  6 16:14 dragon.txt
    drwxr-xr-x 2 root     root     4096 May  6 16:14 ./

    13 字符串处理

    printf格式化输出

    输出类型 说明
    %ns 输出字符串,n是数字指代输出几个字符
    %ni 输出整数,n代表输出几个数字
    %m.nf 输出浮点数,m和n分别代表,输出位数和小数位数,如%8.2f,表示总共输出8位,小数部分2位,整数部分6位
    输出格式 说明
    a 输出警告声音
     输出退格键
    f 清楚屏幕
    换行
    回车
    水平输出退格键,Tab键
    v 垂直输出退格键,Tab键

    printf和其他命令一起使用

    root@ubuntu:/home/yanyanzhang/shell_study# printf '%s' $(cat demo.txt)
    NAMEAGEzhang10wang20li30root@ubuntu:/home/yanyanzhang/shell_study# cat demo.txt 
    NAME    AGE
    zhang    10
    wang    20
    li        30

    加上换行和制表符

    root@ubuntu:/home/yanyanzhang/shell_study# printf '%s	%s	
    ' $(cat demo.txt)
    NAME    AGE    
    zhang    10    
    wang    20    
    li    30    

    awk

    awk '条件1 {动作1} 条件2{动作2} ....'  文件名  说明:条件和动作必须被单引号包裹。

    条件:

    x>10 : 判断变量x是否大于10

    x == y,是否相等

    A ~ B,字符串A中是包含能匹配B表达式的子字符串

    A !~ B,字符串A中是不包含能匹配B表达式的子字符串

    动作:

    格式化输出

    控制流程语句

    root@ubuntu:/home/yanyanzhang/shell_study# cat demo1.txt 
    ID    NAME    LINUX    PHP    JAVA    PYTHON    C
    1    zhang    100    100    100    100    100
    2    wang    90    90    90    90    90
    3    li    80    80    80    80    80
    4    zhao 70    70    70    70    70
    5    sun    60    60    60    60    60
    root@ubuntu:/home/yanyanzhang/shell_study# awk '{printf $1"	" $2"	" $4"	
    "}' demo1.txt 
    ID    NAME    PHP    
    1    zhang    100    
    2    wang    90    
    3    li    80    
    4    zhao    70    
    5    sun    60    

    printf不能输出百分号, print可以

    root@ubuntu:/home/yanyanzhang/shell_study# df -h
    Filesystem      Size  Used Avail Use% Mounted on
    udev            1.9G     0  1.9G   0% /dev
    tmpfs           393M   46M  347M  12% /run
    /dev/sda1        19G   12G  6.1G  66% /
    tmpfs           2.0G  216K  2.0G   1% /dev/shm
    tmpfs           5.0M  4.0K  5.0M   1% /run/lock
    tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
    tmpfs           393M   64K  393M   1% /run/user/1000
    root@ubuntu:/home/yanyanzhang/shell_study# df -h |grep -v "Size"| awk '{print $1 "	" $5 "	" }'
    udev    0%    
    tmpfs    12%    
    /dev/sda1    66%    
    tmpfs    1%    
    tmpfs    1%    
    tmpfs    0%    
    tmpfs    1%    

    判断根分区的百分比超过90%,输出提示信息

    root@ubuntu:/home/yanyanzhang/shell_study# df -h | grep "/dev/sda1"
    /dev/sda1        19G   12G  6.1G  66% /
    root@ubuntu:/home/yanyanzhang/shell_study# df -h | grep "dev/sda1" | awk  '{print $5}'
    66%
    root@ubuntu:/home/yanyanzhang/shell_study# df -h | grep "dev/sda1" | awk  '{print $5}' | cut -d"%" -f1
    66

    awk的执行条件

    条件类型 条件 说明
    awk保留字 BEGIN 在awk程序一开始,尚未读取任何数据之前执行,BEGIN后的动作只在程序开始前执行一次
      END 同上,程序结束前执行,执行一次

    BEGIN

    root@ubuntu:/home/yanyanzhang/shell_study# df -h | grep "dev/sda1" | awk  'BEGIN{printf "----start----
    "}  {print $5}' | cut -d"%" -f1
    ----start----
    66

    END

    root@ubuntu:/home/yanyanzhang/shell_study# df -h | grep "dev/sda1" | awk  'END{printf "----end----
    "}  {print $5}' | cut -d"%" -f1
    66
    ----end----

    输出linux成绩大于等于80分的同学姓名

    root@ubuntu:/home/yanyanzhang/shell_study# cat demo1.txt 
    ID    NAME    LINUX    PHP    JAVA    PYTHON    C
    1    zhang    100    100    100    100    100
    2    wang    90    90    90    90    90
    3    li    80    80    80    80    80
    4    zhao 70    70    70    70    70
    5    sun    60    60    60    60    60
    root@ubuntu:/home/yanyanzhang/shell_study# cat demo1.txt | grep -v "NAME" | awk '$3 >= 80 {printf $2 "
    "}'
    zhang
    wang
    li

    如果想让awk识别正则,必须用//包含才行

    awk的执行过程是,循环读取一行的内容为 $0,然后一行中每列分别为$1,$2,.... $n,匹配其实是匹配的$0里面的内容。printf 不指定,就是打印所有列

    例如,打印包含z的的所有行

    root@ubuntu:/home/yanyanzhang/shell_study# cat demo1.txt 
    ID    NAME    LINUX    PHP    JAVA    PYTHON    C
    1    zhang    100    100    100    100    100
    2    wang    90    90    90    90    90
    3    li    80    80    80    80    80
    4    zhao 70    70    70    70    70
    5    sun    60    60    60    60    60
    root@ubuntu:/home/yanyanzhang/shell_study# awk '/z/ {print}' demo1.txt 
    1    zhang    100    100    100    100    100
    4    zhao 70    70    70    70    70

    在指定列中去匹配

    root@ubuntu:/home/yanyanzhang/shell_study# cat demo1.txt 
    ID    NAME    LINUX    PHP    JAVA    PYTHON    C
    1    zhang    100    100    100    100    100
    2    wang    90    90    90    90    90
    3    li    80    80    80    80    80
    4    zhao 70    70    70    70    70
    5    sun    60    60    60    60    60
    root@ubuntu:/home/yanyanzhang/shell_study# awk '/z/ {print}' demo1.txt 
    1    zhang    100    100    100    100    100
    4    zhao 70    70    70    70    70

    # 第二列中是否包含字符串zhan,包含就打印 root@ubuntu:/home/yanyanzhang/shell_study# awk ' $2 ~ /zhan/ {print $1 " " $2 " " $3 " "}' demo1.txt 1 zhang 100

    awk的内置变量

    awk内置变量 作用
    $0 代表awk所读入的整行数据,awk是一行一行读入数据的
    $n 代表目前读入行的第几个字段,也就是第几列
    NF 当前拥有的列总数
    NR 当前awk所处理的行,是总数据的第几行
    FS 用户自定义分隔符,awk默认的分隔符是任何空格,如果想使用其他的分隔符,如:,就需要FS变量定义
    ARGC 命令行参数个数
    ARGV 命令行参数数组
    FNR 当前文件中的当前记录数(对输出文件起始为1)
    OFMT 数值的输出格式,模式是%.6g
    OFS     输出字段的分隔符,默认是空格

    输出,cut可以替代

    root@ubuntu:/home/yanyanzhang/shell_study# cat /etc/passwd | grep /bin/bash
    root:x:0:0:root:/root:/bin/bash
    yanyanzhang:x:1000:1000:yanyan zhang,,,:/home/yanyanzhang:/bin/bash
    rootyanyanzhangroot@ubuntu:/home/yanyanzhang/shell_study# cat /etc/passwd | grep /bin/bash | awk 'BEGIN{FS=":"} {print $1}'
    root
    yanyanzhang
    root@ubuntu:/home/yanyanzhang/shell_study# cat /etc/passwd | grep /bin/bash | cut -d ":" -f 1
    root
    yanyanzhang

    条件输出,cut无法替代

    root@ubuntu:/home/yanyanzhang/shell_study# cat /etc/passwd | awk 'BEGIN{FS=":"} $3>=900 {print $1}'
    nobody
    yanyanzhang
    mysql

    sed:用于数据的选取,替换,删除,新增等命令。

    命令 作用
    -n 一般sed命令会把所有数据都输出到屏幕上,通过n选择输出第几行
    -e 允许对输入数据应用多条sed命令编辑
    -r  在sed中支持正则表达式
    -f 脚本名称 从sed脚本中读入sed操作,和awk -f 相似
    -i 用sed命令修改结果直接修改读取的文件,而不是由屏幕输出动作
    a : 追加,在当前行后面添加一行或多行,添加多行时,除最后一行外,每行末尾都需要用""代表数据未完结
    c : 行替换,同上
    i : 插入,同上
    d: 删除,删除指定的行

    # TODO

  • 相关阅读:
    javaWeb应用 ssm架构 三方外卖系统
    字节跳动2017秋招-前端工程师
    原码补码反码
    MVVM设计模式
    初始化 react 项目
    antd-mobile定制主题
    jeecg-boot 在线代码生成记
    jeecg-boot 开源代码 问题记录
    idea 导入maven 项目一点反应没有,无识别
    layui 搜索加动态添加列
  • 原文地址:https://www.cnblogs.com/meloncodezhang/p/14726734.html
Copyright © 2011-2022 走看看