Shell总结

1. Shell分类

简介:
普通意义上的shell就是可以接受用户输入命令的程序。它之所以被称作shell,是因为它隐藏了操作系统底层的细节。同样,Unix下的图形用户界面GNOMEKDE,有时也被叫做“虚拟shell”或“图形shell”。

分类:
Linux Shell的种类很多,目前流行的Shell包括ash、bash、ksh、csh、zsh等,种类多了,也就有了标准化的要求,这就是POSIX的由来。

可移植操作系统接口(英语:Portable Operating System Interface,缩写为POSIX)是IEEE为要在各种UNIX操作系统上运行软件,而定义API的一系列互相关联的标准的总称,其正式称呼为IEEE Std 1003,而国际标准名称为ISO/IEC 9945。

用户可以通过查看/etc/shells 文件中的内容来查看自己主机中当前有哪些种类的Shell,命令如下(下面是在Linux 主机中查看信息的结果):

┌──(root💀kali)-[~]
└─# cat /etc/shells                                                                                     16 ⨯
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/usr/bin/bash
/bin/rbash
/usr/bin/rbash
/bin/dash
/usr/bin/dash
/bin/zsh
/usr/bin/zsh
/usr/bin/tmux
/usr/bin/screen
/usr/bin/pwsh
/opt/microsoft/powershell/7/pwsh

  • ash
    ash Shell是由Kenneth Almquist编写的,是Linux 中占用系统资源最少的一个Shell,它只包含24个内部命令,因而使用起来很不方便。
  • bash
    bash是Linux系统默认使用的Shell,它由Brian Fox 和Chet Ramey共同完成,是BourneAgain Shell的缩写,内部命令一共有40 个。Linux 使用它作为默认的Shell是因为它具有以下特色:

可以使用类似DOS下面的doskey的功能,用上下方向键查阅和快速输入并修改命令。
通过自动查找匹配的方式,给出以某字串开头的命令。
包含了自身的帮助功能,你只要在提示符下面键入help就可以得到相关的帮助信息。

  • ksh
    ksh是Korn Shell的缩写,由Eric Gisin编写,共有42 条内部命令。该Shell最大的优点是几乎和商业发行版的ksh 完全相容,这样就可以在不用花钱购买商业版本的情况下尝试商业版本的性能了。
    用于编写 script 的 shell,从可移植性和普遍性上考虑,建议用 ksh。
    因为 POSIX 1003.2 就是以 ksh 为蓝本的。而 bash 又是遵循POSIX 写的。但 bash 除 linux 外,应用较少。而且,有些 ksh93 中的特性 bash 中没有,如 associative arrays。

  • csh
    csh 是Linux 比较大的内核,它由以William Joy 为代表的共计47 位作者编成,共有52个内部命令。该Shell其实是指向/bin/tcsh这样的一个Shell,也就是说,csh其实就是tcsh。

  • zsh
    zsh是Linux 最大的Shell之一,由Paul Falstad完成,共有84 个内部命令。 zsh具有如下特性:

更高效
更好的自动补全
更好的文件名展开(通配符展开)
更好的数组处理
可定制性高

如果只是一般的用途,没有必要安装这样的Shell。


查看当前用户shell:
echo $SHELL


$SHELL是一个环境变量,它记录了Linux 当前用户所使用的Shell类型。用户可以通过直接输入各种Shell的二进制文件名(因为这些二进制文件本身是可以被执行的),来进入到该Shell下,比如进入sh可以直接输入:

┌──(root💀kali)-[~]
└─# /bin/sh                             
sh-5.1# 

这个命令为用户又启动了一个Shell,这个Shell在最初登录的那个Shell之后,称为下级的Shell或子Shell。使用命令:

sh-5.1# exit
exit
  • 可以退出这个子Shell。

2. Shell内建命令

所谓 Shell 内建命令,就是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件。

例如,cd 命令,虽然我们一直在使用它,但如果不加以注意很难意识到它与普通命令的性质是不一样的:该命令并不是某个外部文件,只要在 Shell 中就一定可以运行这个命令。

可以使用 type 来确定一个命令是否是内建命令:

┌──(root💀kali)-[~]
└─# type cd                                                                                             16 ⨯
cd is a shell builtin
                                                                                                             
┌──(root💀kali)-[~]
└─# type ifconfig
ifconfig is /usr/sbin/ifconfig

由此可见,cd 是一个 Shell 内建命令,而 ifconfig 是一个外部文件,它的位置是/usr/sbin/ifconfig。

$PATH变量包含的目录中几乎聚集了系统中绝大多数的可执行命令,它们都是外部命令。

通常来说,内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork创建子进程并exec该命令,但是Shell的内建命令例外,执行内建命令相当于调用Shell进程中的一个函数,并不创建新的进程。

内建命令有mkdircdtouch等等,使用 help或者 man bash-builtins 查看内建命令

3. shell内部变量和环境变量

在shell的解析环境中存在的变量,包括全局变量局部变量,变量前加local成为局部变量
例子:

#!/bin/bash

globalVar1="hello"

function test()
{
    globalVar2="world"
    local localVar="part"    #局部变量
    echo $localVar
}

#调用函数
test

echo $globalVar1 $globalVar2 $localVar

结果:

part
hello world

环境变量:


  • 前言:
  1. 环境变量是操作系统环境设置的变量,适用于整个系统的用户进程;

  2. 环境变量可以在命令中设置,但是用户注销的时候将会丢失这些设置值;

  3. 若要重复适用,则最好在.profile中定义;环境变量的使用与本地变量的使用方法相同,

  4. 但是在使用之前,必须用export命令导出。


Linux中环境变量包括系统级和用户级,系统级的环境变量是每个登录到系统的用户都要读取的系统变量,而用户级的环境变量则是该用户使用系统时加载的环境变量,所以管理环境变量的文件也分为系统级和用户级的。


按变量的生存周期来划分,Linux变量可分为两类:

  1. 永久的:需要修改配置文件,变量永久生效

  2. 临时的:使用export命令声明即可,变量在关闭shell时失效


系统级:

  1. /etc/environment:是系统在登录时读取的第一个文件,该文件设置的是整个系统的环境,只要启动系统就会读取该文件,用于为所有进程设置环境变量。系统使用此文件时并不是执行此文件中的命令,而是根据KEY=VALUE模式的代码,对KEY赋值以VALUE,因此文件中如果要定义PATH环境变量,只需加入一行形如 PATH=$PATH:/xxx/bin的代码即可

  2. /etc/profile:此文件是系统登录时执行的第二个文件。 为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行。并从/etc/profile.d目录的配置文件中搜集shell的设置。(/etc/profile可以用于设定针对全系统所有用户的环境变量,环境变量周期是永久性)

3./etc/bashrc:是针对所有用户的bash初始化文件,在此中设定的环境变量将应用于所有用户的shell中,此文件会在用户每次打开shell时执行一次。(即每次新开一个终端,都会执行/etc/bashrc)。


用户级(这些文件处于家目录下):

  1. ~/.profile:对应当前登录用户的profile文件,用于定制当前用户的个人工作环境(变量是永久性),每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件。这里是推荐放置个人设置的地方

  2. ~/.bashrc:该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件被读取。(~/.bashrc只针对当前用户,变量的生命周期是永久的)
    不推荐放到这儿,因为每开一个shell,这个文件会读取一次,效率肯定有影响。

  3. ~/.bash_profile or ~/bash_login:
    ~/.bash_profile是交互式login 方式进入 bash 运行的,~/.bashrc 是交互式 non-login 方式进入 bash 运行的。通常二者设置大致相同,所以通常前者会调用后者。每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次。默认情况下,它设置一些环境变量,执行用户的.bashrc文件。(如果~/目录下没有.bash_profile则新建立一个)这里是推荐放置个人设置的地方
    当一个shell关闭时,在.bash_profile中定义的系统变量则会失效。因此,每打开一个新的shell时都要运行一次source bash_profile,而且针对当前用户

  4. ~/.bash_logout:当每次退出系统(退出bash shell)时,执行该文件。另外/etc/profile中设定的变量(全局)可以作用于任何用户,而~/.bashrc等中设定的变量(局部)只能继承 /etc/profile中的变量,他们是"父子"关系。


在登录Linux时要执行文件的过程如下:

在刚登录Linux时,首先启动 /etc/profile 文件,然后再启动用户目录下的 ~/.bash_profile~/.bash_login~/.profile文件中的其中一个,用户主目录下文件的执行的顺序为:

~/.bash_profile -> ~/.bash_login -> ~/.profile

如果 ~/.bash_profile文件存在的话,一般还会执行 ~/.bashrc文件。

因为在 ~/.bash_profile文件中一般会有下面的代码:

if [ -f  ~/.bashrc ]; then
   . ./.bashrc
fi

~/.bashrc中,一般还会有以下代码:

if [ -f  /etc/bashrc ]; then
   . /etc/bashrc
fi

所以,~/.bashrc会调用 /etc/bashrc文件。最后,在退出shell时,还会执行 ~/.bash_logout文件。
执行顺序为:

/etc/profile -> (~/.bash_profile | ~/.bash_login | ~/.profile) -> ~/.bashrc -> /etc/bashrc -> ~/.bash_logout

/etc/profile/etc/environment等各种环境变量设置文件的用处

1)先将export LANG=zh_CN加入/etc/profile,退出系统重新登录,登录提示显示英文。

2)先将/etc/profile 中的export LANG=zh_CN删除,将LNAG=zh_CN加入/etc/environment,退出系统重新登录,登录提示显示中文。

用户环境建立的过程中总是先执行/etc/profile,然后再读取/etc/environment

为什么会有如上所叙的不同呢?而不是先执行/etc/environment,后执行/etc/profile呢?
这是因为/etc/environment是设置整个系统的环境,而/etc/profile是设置所有用户的环境,前者与登录用户无关,后者与登录用户有关。

系统应用程序的执行与用户环境可以是无关的,但与系统环境是相关的,所以当你登录时,你看到的提示信息,如日期、时间信息的显示格式与系统环境的LANG是相关的,缺省LANG=en_US,如果系统环境LANG=zh_CN,则提示信息是中文的,否则是英文的。

对于用户的shell初始化而言是先执行/etc/profile,再读取文件/etc/environment;对整个系统而言是先行/etc/environment

登陆系统时的顺序应该是:

/etc/enviroment --> /etc/profile -->HOME/.profile−−>HOME/.env (如果存在)

/etc/profile 是所有用户的环境变量

/etc/enviroment是系统的环境变量

登陆系统时shell读取的顺序应该是:

/etc/profile ->/etc/enviroment -->HOME/.profile−−>HOME/.env

原因是用户环境和系统环境的区别,如果同一个变量在用户环境(/etc/profile)和系统环境(/etc/environment)有不同的值,那应该是以用户环境为准。

Linux中常见的环境变量有:

  1. PATH:指定命令的搜索路径

  2. HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)

  3. HISTSIZE:指保存历史命令记录的条数。

  4. LOGNAME:指当前用户的登录名。

  5. HOSTNAME:指主机的名称,许多应用程序如果要用到主机名的话,通常是从这个环境变量中来取得的。

  6. SHELL:指当前用户用的是哪种Shell。

  7. LANG/LANGUGE:和语言相关的环境变量,使用多种语言的用户可以修改此环境变量。

  8. MAIL:指当前用户的邮件存放目录。

  9. PS1:命令基本提示符,对于root用户是#,对于普通用户是$。

  10. PS2:附属提示符,默认是“>”。

备注:可以通过修改此环境变量来修改当前的命令符,比如下列命令会将提示符修改成字符串“Hello,MyNewPrompt ”。

# PS1="Hello,My NewPrompt"

注意:上述变量的名字并不固定,如HOSTNAME在某些Linux系统中可能设置成HOST

当然,我所列举的上述环境变量并非穷尽列出!

  • Linux修改和查看环境变量的命令!
  1. echo 显示某个环境变量值 echo $PATH

  2. export 设置一个新的环境变量 export HELLO="hello" (可以无引号),在shell的命令行下直接使用[export 变量名=变量值]定义变量,该变量只在当前的shell(BASH)或其子shell(BASH)下是有效的,shell关闭了,变量也就失效了,再打开新shell时就没有这个变量,需要使用的话还需要重新定义。

  3. env 显示所有环境变量

  4. set 显示本地定义(系统中已经存在)的shell变量以及设置shell变量的新变量值,如果未指定值,则该变量值将被设为NULL。

  5. unset 清除环境变量 unset HELLO

  6. readonly 设置只读环境变量 readonly HELLO ,如果使用了readonly命令的话,变量就不可以被修改或清除。


两种方法设置环境变量

export varname=value

或者

varname=value
export varname

环境变量在进程间是父传子单向传递的
子进程对环境变量修改,不会影响父进程,例子:father.shson.sh

  • father.sh
#!/bin/bash

export varName="father"

./son.sh
echo $varName
  • son.sh
#!/bin/bash

echo $varName
export varName="son"
  • ./father.sh结果:
father
father

删除变量:unset varName

4. shell的执行:

test.sh

#!/bin/sh
echo HelloWorld
cd ..   #cd不影响父进程
ls

#!/bin/sh(shebang)不可缺少

  1. ./test.sh

  2. /bin/sh test.sh 这种方法不需要脚本有可执行权限,要有可读权限

弊端:要关注当前脚本用的什么解释器

  1. 直接在bash界面写 (cd ..;ls -l) 和编写shell文件效果一样

  2. source ./test.sh 不产生子进程,相当于导入窗口执行,常用于加载配置文件: source /etc/profile, source. 是一样的

5. 基本语法:

  • 变量赋值
    VARNAME=value
    等号两边不能有空格,留了空格就是一个命令+两个参数
  • 使用变量
    $VARNAME 或者 ${VARNAME}
    a=1
    aa="hello"

    ${a}a
    ${aa}
    #使用花括号来限定变量名的范围
  • 文件通配符进行文件名替换:
    *: 任意多字符
    ?:任意单个字符
    [若干字符]: 匹配方括号中的某个字符,eg: ls [1-4].txtls [1234].txt
  • 参数拓展:
touch 1.txt 2.txt 3.txt 4.txt  #等同下面的一行
touch {1,2,3,4}.txt

示例: mkdir -p day{1..10}/0{1_dog,2_cat,3_lufei}

  • 命令代换:将命令的标准输出的内容变为值
#两种写法
echo `date`
echo $(date)

应用:不管在何路径调用脚本,都要在脚本所在目录创建a.txt

#!/bin/bash

absolutePath=$(cd `dirname $0`;pwd)
cd $absolutePath
touch a.txt
  • `“反引号”, 如果被“反引号”括起来,表示里面需要执行的是命令。比如`dirname $0`, 就表示需要执行 dirname $0 这个命令。

  • "" , 被双引号括起来的内容, 里面出现 $ (美元符: 表示取变量名)。 `(反引号: 表示执行命令) \(转义符: 表示转义), 其余字符才表示字符串。

  • '', 被单引号括起来的内容, 里面所有字符都表示字符串, 包括上面所说的 三个特殊字符。

命令行状态下单纯执行 cd `dirname $0`是毫无意义的,因为它返回到/usr/bin路径。
这个命令写在脚本文件里才有作用,他返回到这个脚本文件放置的目录,并可以根据这个目录来定位所要运行程序的相对位置(绝对位置除外)。

  • $0:当前Shell程序的文件名
  • dirname $0:获取当前Shell程序的路径
  • cd `dirname $0`,进入当前Shell程序的目录

  • 算数代换,四种写法
var=88
echo $[var+1]
echo $((var+1))
echo $[$var+1]
echo $(($var+1))
  • 转义字符
echo \$SHELL    #输出 SHELL
  • shell中的真假
    返回0表示真,非0表示假,通过 $?获取上一条命令的返回状态
test 表达式
[ 表达式 ]
    中括号是一个单独的命令,后面的参数都是作为该命令的参数
    所以要留空格

    ( EXPRESSION )
        测试该表达式是否为真

   ! EXPRESSION
        取反

   EXPRESSION1 -a EXPRESSION2
        逻辑与

   EXPRESSION1 -o EXPRESSION2
        逻辑或

   -n STRING
        判断字符串不是空串

        注意坑:

            test -n $var

   -z STRING
        判断字符串长度为0

   STRING1 = STRING2
        判断字符串相等

   STRING1 != STRING2
        判断字符串不等

   INTEGER1 -eq INTEGER2
        判断整数相等

   INTEGER1 -ge INTEGER2
        判断整数1>=整数2

   INTEGER1 -gt INTEGER2
        判断整数1>整数2

   INTEGER1 -le INTEGER2
        判断整数1<=整数2

   INTEGER1 -lt INTEGER2
        判断整数1<整数2

   INTEGER1 -ne INTEGER2
        判断整数1!=整数2

   FILE1 -nt FILE2
        判断文件1比文件2新(指最后修改时间)

   FILE1 -ot FILE2
        判断文件1比文件2旧

   -b FILE
        块设备

   -c FILE
        字符设备

   -d FILE
        判断是否目录

   -e FILE
        单纯判断文件是否存在

   -f FILE
        判断文件是一个普通文件

   -h FILE
   -L FILE
        判断是否一个符号链接

   -k FILE
        判断文件的粘着位是否被设置

   -p FILE
        判断文件是否是一个命名管道
   -r FILE
        判断文件是否有读权限

   -s FILE
        判断文件存在并且大小大于0字节

   -S FILE
        判断文件是否是一个socket文件

   -t FD
        判断某个文件描述符被终端打开

   -w FILE
        判断是否有写权限

   -x FILE
        有执行权限
  • 分支结构
#!/bin/bash

if [ -f /bin/bash ]
then 
    echo "/bin/bash is a file"
else
    echo "/bin/bash is not a file"
fi

:永远为真, true 为真, false 为假

注意:如果 then 和 if 写在一行,需要加 ;示例:

#!/bin/bash

echo "is it morning,please answer yes or no"
read YES_OR_NO              #read读取用户输入
if [ $YES_OR_NO = "yes" ]   #if开始
then
    echo "good morning"
elif [ $YES_OR_NO = "no" ]; then 
    echo "good afternoon"
else 
    echo "not recognized"
fi              #fi结束
  • shell的与、或
    与的短路特性,前面条件失败,后面条件也不执行
make && sudo make install

或的特性,前面的执行成功,后面的命令就不执行了,注意与、或的区别

echo "a" || echo "b"   #输出a
echo "a" && echo "b"   #输出a b
  • case分支
#!/bin/bash

echo "is it morning?please answer yes or no"
read YES_OR_NO

case "$YES_OR_NO" in
    yes|y|Yes|YES)          #条件
        echo "good morning"
        ;;                  #相当于break
    [nN][oO])
        echo "good afternoon"
        ;;
    *)
        echo "not recognized"
        ;;
esac                        #结束
  • 循环语句
    for循环,相当于 for value : range
#!/bin/bash

for fruit in apple banana pear
do
    echo "I like $fruit"
done

从1加到100,例子:

#!/bin/bash

sum=0
for i in {1..100}
do
    sum=$[sum+i]
done
echo $sum

判断文件类型:

#!/bin/bash

for f in `ls`
do
    if [ -f $f ]
    then
        echo "$f 这是普通文件"
    elif [ -d $f ]
    then
        echo "$f 这是目录文件"
    else
        echo "$f 其他类型文件"
    fi
done
  • 位置参数以及shift
$0          相当于C语言main函数的argv[0]
$1、$2...    这些称为位置参数(Positional Parameter),相当于C语言main函数的argv[1]、argv[2]...   (argv 是 argument vector的缩写)
$#          相当于C语言main函数的argc - 1,注意这里的#后面不表示注释,argc 是 argument count的缩写
$@          表示参数列表"$1" "$2" ...,例如可以用在for循环中的in后面。
$*          表示参数列表"$1" "$2" ...,同上
$?          上一条命令的Exit Status
$$          当前进程号

位置参数默认就支持10个 ,当然$@还是支持n个
可以配合shift来进行参数左移,来操作不定参数

输出
echo -n 表示不换行
echo -e 解析转义字符
echo -e "123\t234"

printf "%d\t%s\n" 123 "hello"
    跟C的printf一样
  • 管道:把一个命令的标准输出重定向到后面进程的标准输入
    |符号,示例:

    • 将标准输入的内容进行缓慢向下查看,要人工操作 cat filename | more -20

    • 比more更加完善的命令,支持回滚,也支持vim: cat filename | less

    • tee 命令通过管道获取标准输出内容,然后输出到屏幕并保存到文件: ls | tee a.txt

  • 文件重定向:

cmd > file              把标准输出重定向到新文件中
cmd >> file             追加

cmd > file 2>&1         标准出错也重定向到1所指向的file里

    2>&1 
        文件描述符2 也重定向到文件描述符1的位置
        标准错误输出也重定向到标准输出的位置

cmd >> file 2>&1
cmd < file
    将file的内容重定向到cmd命令的标准输入
cmd < file1 > file2     输入输出都定向到文件里
cmd < &fd               把文件描述符fd作为标准输入

cmd > &fd               把文件描述符fd作为标准输出

cmd < &-                关闭标准输入
  • 函数:
    完整写法:function()可以忽略其中一个,只能返回int类型的值
#!/bin/bash     

function f()        #function 或者 () 可以忽略其中一个,但不能同时不写
{
    echo "shdfjh"
    return 1
}
f
echo $?
  • 函数递归遍历目录:
#!/bin/bash

function f
{
    local dir="$1"
    for f in `ls $1`
    do
        if [ -f "$dir/$f" ]
        then
            echo "$dir/$f is a file"
        elif [ -d "$dir/$f" ]
        then
            echo "$dir/$f is a dir"
            f "$dir/$f"
        else
            echo "$dir/$f is not recognized" 
        fi
    done
}

f .     #函数调用可以加参数

输出:

./assets is a dir
./assets/css is a dir
./assets/css/bulma.css is a file
./assets/css/hkzclarity.css is a file
./assets/css/hkzclarity.css.map is a file
./assets/css/prism.css is a file
./assets/css/scss is a dir
./assets/css/scss/hkzclarity.scss is a file
./assets/js is a dir
./assets/js/prism.js is a file
./author.hbs is a file
./default.hbs is a file
./error.hbs is a file
./index.hbs is a file
./LICENSE is a file
./package.json is a file
./page-about.hbs is a file
./partials is a dir
./partials/post_loop.hbs is a file
./post.hbs is a file
./README.md is a file
./screenshots is a dir
./screenshots/Author.png is a file
./screenshots/Front.png is a file
./screenshots/Mobile_Front.png is a file
  • 脚本的调试:
    -n   遍历一下脚本,检查语法错误
    -v   一遍执行脚本一遍将解析到的脚本输出来
    -x   执行脚本的同时打印每一句命令,把变量的值都打印出来  (常用)

    打开调试的方法
        1. bash -x  脚本.sh
        2. 脚本开头 使用 #!/bin/bash -x
        3. 脚本中显式的使用 set -x 打开   使用 set +x 关闭调试
  • 正则表达式:
1 以S开头的字符串^S
2 以数字结尾的字符串
    [0123456789]   匹配任意数字
    [0-9]
    \d
    $               匹配字符串结尾

    [0-9]$

3 匹配空字符串(没有任何字符)
    ^$
4 字符串只包含三个数字
    ^\d\d\d$
    ^\d{3}$
        {n} 花括号括起来一个数字,表示前面的单元重复n次

5 字符串只有3到5个字母
    控制最少重复次数和最大的重复次数

    {m,n} m表示前面单元最小重复次数,n表示最大重复次数

    [a-zA-Z]   表示大小写字母  如果中括号中有多个区间,区间之间不要留空格或其他分隔符

    ^[a-zA-Z]{3,5}$


6 匹配不是a-z的任意字符
    [^a-z]    中括号中第一个字符如果是^,表示区间取反
    ^[^a-z]$

7 字符串有0到1个数字或者字母或者下划线
    {0,1} 表示重复0-1次
    ?     也可以表示0-1次重复

    ^[0-9a-zA-Z_]?$
    ^\w?$


8 字符串有1个或多个空白符号(\t\n\r等)
    \s  表示空白字符 包括 \t\n\r ....
    {1,}   表示重复1-n  跟+号一样

    ^\s+$


9 字符串有0个或者若干个任意字符(除了\n)
    .  代表任意字符,除了\n
    ^.{0,}$   花括号中两个参数置空表示重复次数任意 0-n
    ^.*$     *表示前面的单元重复0-n次

    ? 0-1
    + 1-n
    * 0-n


10 匹配0或任意多组ABC,比如ABC,ABCABCABC
    使用小括号来讲多个单元重新组合成为一个单元

    ^(ABC)*$


11 字符串要么是ABC,要么是123
    | 表示选择,选择两边的正则匹配一个

    ^ABC$|^123$
    ^(ABC|123)$     小括号也可以将选择范围控制在括号内


12 字符串只有一个点号  
    做转义 还是使用\

    ^\.$

13 匹配十进制3位整数             
    100 - 999
    ^[1-9][0-9]{2}$


    匹配十进制 0-999 的数字
        分段
            一位数
                [0-9]
            两位数
                10-99
                [1-9][0-9]
            三位数
                [1-9][0-9]{2}


        ^([0-9]|[1-9][0-9]{1,2})$



14 匹配0-255的整数

    匹配 ip 

        分段
            一位数
                [0-9]
            两位数
                10-99
                [1-9][0-9]

            三位数
                100-199
                    1[0-9]{2}

                200-249
                    2[0-4][0-9]

                250-255
                    25[0-5]

15 匹配端口号
    0-65535

16 email
    [\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?
    
     基础的正则
        +?* 是普通字符
    扩展的正则
        +?* 是特殊字符

    perl的正则
        最常用

        perl正则在扩展正则之上添加了一些特殊符号
            \d \w \s ....
  • sort
    命令从标准输入中读取数据然后按照字符串内容进行排序
    -f 忽略字符大小写
    -n 比较数值大小
    -t 指定分割符,默认是空格或者tab
    -k 指定分割后进行比较字段
    -u 重复的行只显示一次
    -r 反向排序
    -R 打乱顺序
        同样的两行洗不乱  
    将/etc/passwd 根据用户id来排序
    sort -t: -k3 -n < /etc/passwd
  • uniq
    去除重复的行,前提是重复的行连续
    -c 显示每行重复的次数
    -d 仅显示重复过的行
    -u 仅显示不曾重复的行
        sort < test.txt | uniq
  • wc
    word count
    -l 统计行数
    -c 统计字节数
    -w 统计单词数
  • grep
 global regular expression print
 -c 只输出匹配行的计数
 -i 不区分大小写
 -H 文件名显示
 -r 递归遍历目录
 -n 显示行号
 -s 不显示不存在或无匹配文本的错误信息
 -v 显示不包含匹配文本的所有行,这个参数经常用于过滤不想显示的行
 -E 使用扩展的正则表达
 -P 使用perl的正则表达式
 -F 匹配固定的字符串,而非正则表达式


 egrep  = grep -E
 fgrep  = grep -F
 rgrep  = grep -r

 grep 默认使用的是基础的正则
 例子:
 981  grep -c sh ss.sh
983  grep -h sh ss.sh
984  grep -h -H  sh ss.sh
985  grep  -H  sh ss.sh
987  grep -r sh .
988  grep -r -n sh .
989  rgrep -n sh .
990  man grep
994  grep  -r -n -v sh .
996  grep  -r -n -P sh$ . 
997  grep  -r -n -P ^.*bin.*$ . 
999  grep  -r -n  ^.*bin.*$ . 
1000  grep  -r -n -F  ^.*bin.*$ .
  • find:搜索文件所在路径
    find pathname -options [-print -exec -ok ...]

    option 选项如下:
        -name 按照文件名查找文件。注意:""不要省略,否则结果有问题
            find . -name "1.txt"
            find . -name "*.sh"
        -perm 按照文件权限来查找文件。
            find . -perm 660
        -user 按照文件属主来查找文件。
        -group 按照文件所属的组来查找文件。
        -mtime -n +n 按照文件的更改时间来查找文件,-n表示文件更改时间距现在n天以内,+n表示文件更改时间距现在
            n天以前。find命令还有-atime和-ctime 选项,但它们都和-mtime选项类似。
        -atime 访问时间
        -ctime 创建时间
        -nogroup 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。
        -nouser 查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。
        -newer file1 ! file2 查找更改时间比文件file1新但比文件file2旧的文件。
        -type 查找某一类型的文件,诸如:
            b - 块设备文件。
            d - 目录。
            c - 字符设备文件。
            p - 管道文件。
            l - 符号链接文件。
            f - 普通文件。
            s - socket文件



        -exec
            find . -name "*.txt" -exec gzip {} \;

            查找当前目录下的txt文件并且打包成为gzip
            每找到一个文件,就会执行exec后面的命令
                gzip ./a/2.txt
                gzip ./a/6.txt

                最后是一个\;  反斜杠不能省,作为当前exec后面命令的结束符



        -ok 
            跟-exec用法一样,但是每找到一个文件要执行后面的命令前会给用户确认
  • xargs:将标准输入的参数整齐的拼凑在一行
    要配合其他命令使用
    docker ps -aq | xargs docker rm -f

    find . -name "*.txt" | xargs -I{} mv {}  xxx/
        -I{} 指定一个替换字符串作为参数替换
  • sed
    文本1 ->  sed + 脚本 -> 文本2 

    ed 编辑器   ->  sed   -> vim 

    sed option 'script' file1 file2 ...             sed 参数  ‘脚本(/pattern/action)’ 待处理文件
    sed option -f scriptfile file1 file2 ...        sed 参数 –f ‘脚本文件’ 待处理文件


        p,  print           打印
        a,  append          追加
        i,  insert          插入
        d,  delete          删除
        s,  substitution    替换
  • awk
    awk option 'script' file1 file2 ...
    awk option -f scriptfile file1 file2 ...

    最常见用法就是过滤哪一列
    xxxx | awk '{print $2}'


    脚本格式
    {actions}                       
        每一行文本都无条件的执行脚本
    /pattern/{actions}
        匹配了模式之后再执行后面的动作
    condition{actions}
        BEGIN
            在遍历文本的第一行之前会执行某个动作
        END
            在遍历完文本之后再去执行某个动作


    ProductA 30
    ProductB 76
    ProductC 55

    在输出表格之前输出表头  产品名字  库存
    输出完表格之后  输出    库存总量 : xxxx

    在遍历之前输出表头
    BEGIN{
        printf "%s\t%s\n","产品","库存";
        sum=0;
    }
    在遍历每一行的过程中输出每一行的内容,将库存加到sum变量
    {
        printf "%s\t%s\n",$1,$2;
        sum+=$2;
    }
    遍历完之后输出sum变量
    END{
        printf "库存总量:%d\n",sum
    }
  • crontab
    linux 系统定时器
    需求,每天什么时候去做什么事情

    /etc/crontab

# m h dom mon dow user  command                                                                            
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly                                        
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )        
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )       
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )      
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容