shell 基本语法

#!  —— Shebang 符号: 说明使用哪种解释器执行shell命令

一、shell中的变量和符号

1.1 通配符

Shell中的通配符 - 苦逼运维 - 博客园

shell常见的通配符,注意与正则稍有不同:

字符

含义

实例

*

匹配0个或多个任意字符

a*b,a与b之间可以有任意长度的字符,也可以没有。

例如:aabcb,ab,azxcb...

?

匹配一个任意字符

a?b,a与b之间必须但也只能存在一个字符,该字符可以是任意字符。    例如:aab,abb,acb...

[list]

匹配list中的任意单个字符

a[xyz]b,a与b之间必须但也只能存在一个字符,该字符只能是x或y或z。 例如:axb,ayb,azb

[!list]

匹配除list中的任意单个字符

a[!a-z]b,a与b之间必须但也只能存在一个字符,该字符不能是小写字母。   例如:aAb,a0b...

[^]

匹配除了中括号的一个字符。

例如[^0-9],匹配除了数字的字符,只会匹配集合中的一个

\

转义符。 让元字符回归本意

例如 echo  \*

1.2 变量

1.2.1 系统变量

$HOME(当前家目录) , $PWD(当前路径的绝对路径名),  $SHELL(默认shell解析器), $USER(当前用户) 等。

1.2.2 自定义变量

1)例如:a=2, 等号左右两边不能有空格,unset a 清空变量值。变量定义规则:字母、数字、下划线,但是不能以数字开头。

2)变量默认类型都是字符串类型,不能直接进行运算,例如 c=1+1 ,输出值为1+1而非2。

3)变量值如果有空格,必须要用双引号或单引号引起来。如b="hello world"

4) 可将变量设置为全局变量,可供其他shell程序使用。格式 export 变量名

1.2.2.1 变量赋值

1、显示赋值

变量名=变量值    // 注意:等号两边没有空格

例如:

ip=192.168.1.1

today=`date +%F`  // 获取当前日志,通过 echo $today 查看变量值。 注意不是单引号,是反引号(~按键上的 符号)

$ echo $today

2022-11-05

today=$(date +%F)  // 反引号   小括号 都可以括起来变量值

2、read 冲键盘读入变量值

read 变量名  // 执行后,手动输入的值就会保存到变量中

read -p “提示信息: ” 变量名

1.2.2.2 变量引用

“ ”(双引号):变量会被展开。

‘’(单引号):变量不会被展开。

例.

$ string="hello shell"         // 定义一个变量

$ echo "-----test $string -----"   // 双引号:展开引用

-----test hello shell -----

$ echo '-----test $string -----'  // 单引号:不展开引用

-----test $string -----

1.2.2.3 命令替换——反引号或者$()

例. 创建一个带日志的文件

$  touch `date +%F`_debug.log

$ ll

-rw-r--r-- 1 z 197121  0 11  5 14:53 2022-11-05_debug.log

或者

$  touch $(date +%F)_err.log

$ ll

-rw-r--r-- 1 z 197121  0 11  5 14:53 2022-11-05_debug.log

1.2.3 特殊变量

变量

含义

$0

当前脚本的文件名。

$n(n≥1)

传递给脚本或函数的第几个参数。例如,第一个参数是 $1,第二个参数是 $2。

$#

传递给脚本或函数的参数个数。

$*

传递给脚本或函数的所有参数。

$@

传递给脚本或函数的所有参数。当被双引号" "包含时,$@ 与 $* 稍有不同。

$?

上个命令的退出状态,或函数的返回值。

$$

当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。

例1. 给脚本文件传递参数

编写下面的代码,并保存为 test.sh:

#!/bin/bash

echo "Process ID: $$"

echo "File Name: $0"

echo "First Parameter : $1"

echo "Second Parameter : $2"

echo "All parameters 1: $@"

echo "All parameters 2: $*"

echo "Total: $#"

运行 test.sh,并附带参数:

[mozhiyan@localhost demo] ./test.sh Shell Linux

Process ID: 5943

File Name: bash

First Parameter : Shell

Second Parameter : Linux

All parameters 1: Shell Linux

All parameters 2: Shell Linux

Total: 2

例2给函数传递参数

编写下面的代码,并保存为 test.sh:

#!/bin/bash

#定义函数

function func(){

    echo "Language: $1"

    echo "URL: $2"

    echo "First Parameter : $1"

    echo "Second Parameter : $2"

    echo "All parameters 1: $@"

    echo "All parameters 2: $*"

    echo "Total: $#"

}

#调用函数

func Java http://c.biancheng.net/java/

运行结果为:
Language: Java
URL: http://c.biancheng.net/java/
First Parameter : Java
Second Parameter : http://c.biancheng.net/java/
All parameters 1: Java http://c.biancheng.net/java/
All parameters 2: Java http://c.biancheng.net/java/
Total: 2

1.2.4 解析器

查看系统中shell解析器的类型。 最常用的就是/bin/sh和/bin/bash。

1.2.5 在文件之间传递变量

$ cat public_var.sh   // 自定义公共变量

#!/usr/bin/bash

export dir_path=$(PWD)   // 通过export 声明为全局变量

export dir2_path=/home/

$ cat 1.sh

#!/usr/bin/bash

. public_var.sh      // 通过. 或者source 方式在子shell中使用 自定义的全局变量

echo "----------------"

echo $dir_path

echo $dir2_path

1.2.6 变量的运算

1.2.6.1 整数运算

方法1: 使用expr。  

加法:+、

减法:- 、

乘法: \* (乘法需要转义)、

除法:/ 、

取余: %

例:expr 1 + 2

方法2: 使用$(())   —— 注意是:双括号。

例: echo $((num1+num2))

方法3:使用$[] 

例: sum=$[num1+num2]

方法4 使用let (推荐)

例:let  sum = num1+num2

1.2.6.2 小数运算 —— 计算器: bc  或者 awk、python

例:

$ echo "scale=2;6/2" | bc

awk 'BEGIN{print 1/2}'

1.2.7 变量内容删除、替换

1.3 重定向

1.3.1 参数解释

符号

说明

0

标准输入

1

标准输出

2

错误输出

/dev/null

Linux中的一个特殊文件,写入该文件的内容都将被丢弃

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  1. 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  2. 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  3. 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

默认情况下,是将 stdout(标准输出) 重定向到 file,command < file 将stdin 重定向到 file。

1.3.2 常用方法

符号

说明

>  (重定向符)

将标准输出重定向到文件

1>

将标准输出重定向到文件,>相同

2>

将错误输出重定向到文件

2>&1

将错误输出重定向到标准输出

&>

将标准输出和错误输出都重定向到文件, 2>&1 可以简写成:&>  或者 >&

例1. "一些内容" 写入到 filename.txt 文件中

$echo "一些内容" > filename.txt  

例2. 将标准输出 和 错误输出 都重定向到/dev/null。

$ command > /dev/null 2>&1

Tips

1>前是可以加数字来说明把什么内容重定向到文件中,默认是把标准输出重定向到文件中

2 这里的 2> 之间不可以有空格2> 是一体的时候才表示错误输出。

1.3.3 /dev/null 文件

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

例. 屏蔽 stdout 和 stderr

$ command > /dev/null 2>&1

1.4 shell中的特殊符号

()  : 在子shell中执行

(()) : 数值比较, 运算 C语言

$() : 命令替换,  等价于 一对反引号

$(()) :整数运算

{}:

${}:

[]:条件测试

[[]]: 条件测试,支持正则 =~

$[]:整数运算

二、条件测试

2.1 数值、字符串、文件测试

格式1: test 条件表达式

格式2: [ 条件表达式 ]   

格式3: [[ 条件表达式 ]]  

2.2 文件测试

[ 操作符 文件或者目录 ]

说明:

1、操作符

-e:是否存在

-d:是否是路径

-f:是否是文件

例:

[  -e  dir | file  ]

[  -d  dir  ]

[  -f file  ]  // 是否存在, 而且是文件

[  -r file  ]  // 当前用户对文件是否有读权限

2.3 数值比较

例.

[ 2 -gt 10 ]  大于

[ 2 -lt 10 ]  小于

[ 2 -eq 10 ]  等于

[ 2 -ne 10 ]  不等于

三、函数

3.1 定义

方法1:

函数名() {

    功能实现;

}

方法2:

function 函数名 {

    功能实现;

}

3.2 调用

函数名

函数名 参数参数2

说明:

传参 $1, $2

变量 local

返回值 return  $?

例: 定义一个函数计算 阶乘

$ ./cal_factorial.sh  6     //  执行脚本: 传给脚本的参数 $1 = 6

---------------120---------------

$ cat cal_factorial.sh

#!/bin/bash

factorial() {    // 函数定义

    fac=1

    for ((i=1;i<$1;i++))

    do

            fac=$[$fac * $i]

    done

    echo "---------------$fac---------------"

}

factorial $1  // 函数调用

四、shell 三剑客

三剑客的格式

grep  ‘字符文件

sed  ‘命令文件

awk ‘条件{命令}’ 文件

Tips

单引号内就是正则表达式的用法。

4.1 grep —— 字符串搜索

grep [选项]… 查找条件 目标文件

说明:

  1. -i:查找时忽略大小写
  2. -v:反向查找,输出与查找条件不相符的行
  3. -f: 对比两个文件的相同行
  4. -c: 匹配的行数
  5. -R: 递归子目录
  6. -n: 显示匹配的具体行号

4.2 sed —— 按行编辑文本(增、删、改、选取、移动等)

读取文本,并根据指定的条件对文本内容进行编辑(增、删、改、移动等),最后输出所有行或者仅输出处理的某些行。

4.2.1 基本语法

sed[选项] '操作' 参数

sed [选项] -f scriptfile 参数

sed 的工作流程主要包括读取、执行和显示三个过程。

  • 读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。
  • 执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。
  • 显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。

在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。

注意:

默认情况下所有的 sed 命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。

4.2.2 常用选项

  • -e 或–expression=:表示用指定命令或者脚本来处理输入的文本文件。
  • -f 或–file=:表示用指定的脚本文件来处理输入的文本文件。
  • -h 或–help:显示帮助。
  • -n、–quiet 或 silent:表示仅显示处理后的结果。
  • -i:直接编辑文本文件。

4.2.3 常用操作

  • a:增加,在当前行下面增加一行指定内容。
  • c:替换,将选定行替换为指定内容。
  • d:删除,删除选定的行。
  • i:插入,在选定行上面插入一行指定内容。
  • p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以 ASCII 码输出。其通常与“-n”选项一起使用。
  • s:替换,替换指定字符。
  • y:字符转换。

1. 选择/打印 指定行

sed -n 'p' test.txt      输出所有内容 ,等同于使用cat

sed -n '3p' test.txt     输出第 3

sed -n '3,5p' test.txt       输出 3~5

sed -n '/[0-9]$/p' test.txt   输出以数字结尾的行

2. 删除指定行

sed  '2,4d'   file_name      删除file_name 24

nl  test.txt  | sed '3d'        删除第 3 行。 nl 命令用于计算文件的行数

nl  test.txt  | sed '/cross/d'    删除包含cross 的行

nl  test.txt  | sed '/cross/!d'   删除不包含cross 的行

sed  '/^[a-z]/d'  test.txt      删除以小写字母开头的行

sed  '/\.$/d'  test.txt         删除以"."结尾的行

sed '/^$/d' test.txt            删除所有空行

3. 替换符合条件的文本

// 在使用 sed 命令进行替换操作时需要用到 s(字符串替换)、c(整行/整块替换)、y(字符转换)命令选项

sed 's/l/L/2' test.txt         将每行中的第2 l替换为L

sed 's/the/THE/g' test.txt       将文件中的所有the替换为THE

sed 's/o//g' test.txt           将文件中的所有o 删除(替换为空串)

sed 's/^/#/' test.txt           在每行行首插入#

sed '/the/s/^/#/' test.txt          在包含the的每行行首插入#

sed 's/$/EOF/' test.txt           在每行行尾插入字符串EOF

sed '3,5s/the/THE/g' test.txt   将第3~5行中的所有the替换为THE

sed '/the/s/o/O/g' test.txt       将包含the 的所有行中的o 都替换为 O

4. 迁移符合条件的文本

// H,复制到剪贴板;gG,将剪贴板中的数据覆盖/追加至指定行;w,保存为文件;r,读取指定文件;a,追加指定内容。

sed '/the/{H;d};$G' test.txt       将包含the的行迁移至文件末尾,{;}用于多个操作

sed '1,5{H;d};17G' test.txt       将第1~5行内容转移至第17行后

sed '/the/wout.file' test.txt         将包含the的行另存为文件out.file

sed '/the/r /etc/hostname' test.txt    将文件/etc/hostname的内容添加到包含the 的每行以后

sed '3aNew' test.txt                 在第3行后插入一个新行,内容为New

sed '/the/aNew' test.txt             在包含the的每行后插入一个新行,内容为New

sed '3aNew1\nNew2' test.txt        在第3行后插入多行内容,中间的\n表示换行

4.2.4 使用脚本编辑文件

使用sed脚本,将多个编辑指令存放到文件中(每行一条编辑指令),通过“-f”选项来调用。

. 将第 1~5 行内容转移至第 17 行后

sed '1,5{H;d};17G' test.txt   

以上操作可以改用脚本文件方式:  

sed -f opt.list  test.txt

$ cat opt.list   // 脚本中的指令

1,5H   将文件中的1--5行复制到剪切板

1,5d    删除文件中的1--5

17G    将复制到剪切板中的1--5行追加到第17行之后

4.3 awk——以字段为单位进行处理(其实就是把一行数据分割,然后进行处理)

4.3.1 基本语法

awk  '条件{命令1} 条件{命令2}...'   file_name 1  file_name 2…

awk  -f  | -v 脚本文件 file_name 1  file_name 2…

说明:

1、sed命令常用于一整行的处理,而awk是将一行分为多个"字段"然后再进行处理,awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。

2、awk隐含循环,条件匹配多少次动作就会执行多少次,如果没有定义匹配条件默认是匹配所有数据行。

3、读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出

4、逐行读取输入文本,并根据指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互的情况下实现相当复杂的文本操作。

4.3.2 常用参数

1.$0   当前处理的行的整行内容, 代表一整行的数据

2.$n   当前处理行的第n个字段(即第n列)

3.NF   当前处理的行的字段个数即每一行拥有的字段总数

4.NR   当前处理的行的行号,即目前处理的是第几行的数据

5.FS   指定每行文本的字段分隔符,缺省为空格或制表位(tab

6.RS   行分隔符,根据RS的定义把资料切割成许多条记录

7.FNR  读取文件的记录行号(从1开始,若读取新的文件依旧是从1开始)

8.OFS  输入字段的分割符(默认是空格)

9.ORS  输出行的分割符,默认为换行符

Tips

1、像\n ,\t,这种符号应该用双引号括起来

2NRNF等变量要用大写,并且不需要 $

1. 查找出/etc/passwd 的用户名、用户 ID、组 ID 等列

$ awk  -F  ’:’  ‘{print $1, $3, $4}’  /etc/passwd

工作原理

2. file_name 文件中的前五行的第一列,第二列的数据列出来 (以[tab]或空格键分隔)

awk 'NR<6{print $1 $2}'  file_name

3. 打印匹配的行  Shell编程三剑客_LIUXU23的博客-CSDN博客_shell三剑客

4. 打印符合条件的行

awk -F":" '{print $1"\t"$2}' passwd         用制表符作为分隔符输出

awk -F[:/] '{print $9}' passwd              []中定义多个分隔符,只要看见其中一个都算作分隔符

awk '{print}' test.txt                     输出所有内容

awk '{print $0}' test.txt                   输出所有内容

awk 'NR==1,NR==3{print}' test.txt         输出第 1~3 行内容

awk '(NR>=1)&&(NR<=3){print}' test.txt    输出第 1~3 行内容

awk 'NR==1||NR==3{print}' test.txt         输出第 1 行、第 3 行内容

awk '(NR%2)==1{print}' test.txt            输出所有奇数行

awk '(NR%2)==0{print}' test.txt            输出所有偶数行

seq 200 | awk '$1%7==0 && $1~/7/'         打印1-200之间所有能被7整除的整数数字

awk '/^root/{print}' passwd                输出以root开头的行

awk '/nologin$/{print}' passwd             输出以 nologin 结尾的行

awk '{print$3}' test.txt                   输出每行中(以空格或制表位分隔)的第3个字段

awk '{print$1,$3}' test.txt                 输出每行中的第13个字段

// 网卡的IP、流量

ifconfig ens33 | awk '/netmask/{print "本机的ip地址是"$2}'  

ifconfig ens33 | awk 'RX p/{print $5"字节"}'

// 根分区的可用量

df -h | awk 'NR==2{print $4}'               

4.3.3 特殊用法

逐行执行开始之前执行什么任务,结束之后再执行什么任务,用BEGIN、END

  • BEGIN一般用来做初始化操作,仅在读取数据记录之前执行一次
  • END一般用来做汇总操作,仅在读取完数据记录之后执行一次

1.  awk 的运算

awk 'BEGIN{x=10;print x}'      如果不用引号awk就当作一个变量来输出了,所有不需要加$

awk 'BEGIN{print x+1}'        x不指定初始值、初始值就为0,如果是字符串则默认为空

awk 'BEGIN{print 1.2+3.4}'     支持小数运算

2. 打印第12

awk -F":" '{print $1" "$2}' passwd  空格需要用双引号引用起来,如果不引默认以变量看待,如果是常量就需要双引号引起来

3. 在打印之前定义字段分隔符为冒号

awk 'BEGIN{FS=":"}{print $1}' passwd

4. 输出低12列,并在第12列中间加分隔符--

awk 'BEGIN{FS=":";OFS="--"}{print $1,$2}' passwd

// OFS定义了输出时以什么为分隔,$1$2中间要同逗号分隔,因为逗号默认被映射为OFS变量,而这个变量默认是空格

5. 把多行合并为一行输出

awk 'BEGIN{ORS=" "}{print $0}' passwd

把多行合并成一行输出,输出的时候自定义以空格分隔每行,本来默认是回车键

4.3.4 高级用法

1. 调用函数getline,读取一行数据的时候并不是等到当前行而是当前行的下一行

seq 10 | awk '{getline;print $0}'

2. if + awk

单分支为if ( ) { }

双分支为if ( ) { }else{ }

多分支为if ( ) { }else if ( ) { }else{ }

单分支 awk -F: '{if(条件判断){执行的指令操作}} 处理对象(文件、管道、标准输入)

双分支 awk -F: '{if(条件判断){执行的指令操作}else{执行的操作指令}} 处理对象(文件、管道、标准输入)

多分支 awk -F: '{if(条件判断){执行的指令操作}else if(条件表达式2){操作指令}else{其他的操作指令}} 处理对象(文件、管道、标准输入)

2. 打印符合条件的行

awk -F: '{if($3<10){print $0}}' /etc/passwd               第三列小于10的打印整行

awk -F: '{if($3<10){print $3}else{print $1}}' /etc/passwd    第三列小于10的打印第三列,否则打印第一列

3. BEGIN-- END

awk 'BEGIN{x=0};/\/bin\/bash$/ {x++;print x,$0};END {print x}' /etc/passwd

// 统计以/bin/bash结尾的行数,等同于grep -c "/bin/bash$" /etc/passwd

BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中的动作;

awk再处理指定的文本;

再执行ENG模式中指定的动作,ENG{ }语句块中,往往会放入打印结果等语句

常用命令

公共命令

调试方式运行shell 脚本——bash -vx  xxx.sh

$ bash -vx 1.sh

#!/usr/bin/bash

. public_var.sh

+ . public_var.sh

#!/usr/bin/bash

export dir_path=$(PWD)

+++ PWD

++ export dir_path=/d/eBook/Shell/test

++ dir_path=/d/eBook/Shell/test

export dir2_path=/home/

++ export dir2_path=/home/

++ dir2_path=/home/

echo "----------------"

+ echo ----------------

----------------

echo $dir_path

+ echo /d/eBook/Shell/test

/d/eBook/Shell/test

echo $dir2_path

+ echo /home/

/home/

查看帮助信息——man cmd

例: man test    //  查看test的帮助信息

type  -a 查看 符号类型;或者 which

例如:

查看环境变量

echo $PATH    // 查看指定变量

set            // 查看所有变量

env           //  查看环境变量

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值