shell学习

什么是shell?

shell是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。

Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

为什么要学习和使用shell?
Shell属于内置的脚本,程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理)语法简单,代码写起来比较轻松,简单易学

shell的分类

cat /etc/shells
在linux中有很多类型的shell,不同的shell具备不同的功能,shell还决定了脚本函数的语法,Linux中默认的shell是 /bash/bash(重点), 流行的shell有ash,bash,ksh,csh,zsh等,不同的shell都有自己的特点以及用途

编写规范:
#!/bin/bash [指定告知系统当前这个脚本要使用的shell解释器]
Shell 相关指令

文件命名规范:
文件名.sh .sh是linux下bash shell的默认后缀

输入输出重定向:

是指不使用系统提供的标准输入端口,而进行重新的指定。换言之,输入重定向就是不使用标准输入端口输入文件,而是使用指定的文件作为输入设备

命令 < 文件 : 将指定文件作为命令的输入设备

[root@localhost ~]# cat /etc/passwd
#这里省略输出信息,读者可自行查看
[root@localhost ~]# cat < /etc/passwd
#输出结果同上面命令相同

命令 << 分界符 表示从标准输入设备中读入,直到遇到分界符才停止,这里的分界符其实就是自定义的字符串

[root@localhost ~]# cat << 0
>c.biancheng.net
>Linux
>0
c.biancheng.net
Linux

命令 < 文件 1 > 文件 2: 将文件 1 作为命令的输入设备,该命令的执行结果输出到文件 2 中。

[root@localhost ~]# cat a.txt
[root@localhost ~]# cat < /etc/passwd > a.txt
[root@localhost ~]# cat a.txt
#输出了和 /etc/passwd 文件内容相同的数据
输出抽定向:(通俗的讲,重定向输出就是把要输出的文件信息写入到一个文件中去,而不是将要输出的文件信息输出到控制台)

命令 > 文件:将命令执行的标准输出结果重定向输出到指定的文件中,如果该文件已包含数据,会清空原有数据,再写入新数据。

命名2 > 文件 : 将命令执行的错误输出结果重定向到指定的文件中,如果该文件中已包含数据,会清空原有数据,再写入新数据。

命令 >> 文件 :将命令执行的标准输出结果重定向输出到指定的文件中,如果该文件已包含数据,新数据将写入到原有内容的后面。

命令 2 >> 文件 : 将命令执行的错误输出结果重定向到指定的文件中,如果该文件中已包含数据,新数据将写入到原有内容的后面。

命令 >> 文件 2>&1
或者
命令 &>> 文件 : 将标准输出或者错误输出写入到指定文件,如果该文件中已包含数据,新数据将写入到原有内容的后面。注意,第一种格式中,最后的 2>&1 是一体的,可以认为是固定写法。

/dev/null文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结构,那么可以将输出重定向到/dev/null;
command > /dev/null

执行shell

多命令顺序执行
多命令顺序执行 ; && ||

shell 脚本的执行
vim test.sh
echo “hello world”

两种方式执行shell脚本
第一种:给文件增加执行权限

通过Bash调用执行脚本
bash test.sh

shell变量

什么是变量?

在一个脚本周期内,其指可以发生改变的量就是变量

变量的命名规则:

基本还c语言,java变量命名要求差不多

test =123
test="$test"456
echo $test
123456

test =${test}789
echo $test
单引号和双引号
[root@localhost ~]$ name=sc
#定义变量name 的值是sc(就是最正直的人,超哥我了!)
[root@localhost ~]$ echo '$name'
$name
#如果输出时使用单引号,则$name原封不动的输出
[root@localhost ~]$ echo "$name"
sc
#如果输出时使用双引号,则会输出变量name的值 sc

[root@localhost ~]$ echo `date`
2018年10月21日星期一18:16:33 CST
#反引号括起来的命令会正常执行
[root@localhost ~]$ echo '`date`'
`date`
#但是如果反引号命令被单引号括起来,那么这个命令不会执行,―date`会被当成普通字符输出
[root@localhost ~]$ echo "`date'"
2018年10月21日星期一18:14:21 CST
#如果是双引号括起来,那么这个命令又会正常执行
反引号
[root@localhost ~]$ echo ls
ls
#如果命令不用反引号包含,命令不会执行,而是直接输出
[root@localhost ~]$ echo `ls`
anaconda-ks.cfginstall.loginstall.log.syslog sh test testfile
#只有用反引号包括命令,这个命令才会执行
[root@localhost ~]$ echo $(date)
2018年10月21日星期一18:25:09 CST
#使用$(命令)的方式也是可以的

变量的分类

  1. 用户自定义变量:这种变量是最常见的变量,由用户自由定义变量和变量的值.
  2. 环境变量:这种变量中主要保存的是和系统操作环境相关的数据,比如当前登录用户,用户的家目录,命令的提示符等.
  3. 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的
  4. 预定义变量:是Bash中已经定义好的变量,变量名不能自定义
用户自定义变量
变量定义
[root@localhost ~]$ 2name="shen chao"
-bash: 2name=shen chao: command not found
#变量名不能用数字开头
[root@localhost ~]$ name = "shenchao"
-bash: name: command not found
#等号左右两侧不能有空格
[root@localhost ~]$ name=shen chao
-bash: chao: command not found
#变量的值如果有空格,必须用引号包含
变量调用
[root@localhost ~]$ name="shen chao"
#定义变量name
[root@localhost ~]$ echo $name #调用变量使用  $变量名
shen chao
#输出变量name的值

变量查看
[root@localhost ~]$ set [选项]
选项:
-u:如果设定此选项,调用未声明变量时会报错(默认无任何提示)
-x:如果设定此选项,在命令执行之前,会把命令先输出一次
+<参数> :取消某个set曾启动的参数。

[root@localhost ~]$ set
BASH=/bin/bash
…省略部分输出…
name='shen chao'
#直接使用set 命令,会查询系统中所有的变量,包含用户自定义变量和环境变量
[root@localhost ~]$ set -u
[root@localhost ~]$ echo $file
-bash: file: unbound variable
#当设置了-u选项后,如果调用没有设定的变量会有报错。默认是没有任何输出的。
[root@localhost ~]$ set -x
[root@localhost ~]$ ls
+ls --color=auto
anaconda-ks.cfginstall.loginstall.log.syslog sh tdir testtestfile
#如果设定了-x选项,会在每个命令执行之前,先把命令输出一次

[root@localhost ~]$ set +x
#取消启动的x参数
变量删除
[root@localhost ~]$ unset 变量名

环境变量

环境变量设置
[root@localhost ~]$  export age="18"
#使用export声明的变量即是环境变量
环境变量查询和删除

env命令和set命令的区别:
set命令可以查看所以变量,而env命令只能查看环境变量.

[root@localhost ~]$ unset gender   #删除环境变量gender
[root@localhost ~]$ env | grep gender
系统默认环境变量
[root@localhost ~]$ env
HOSTNAME=localhost.localdomain      #主机名
SHELL=/bin/bash                     #当前的shell
TERM=linux                          #终端环境
HISTSIZE=1000                       #历史命令条数
SSH_CLIENT=192.168.4.1594824 22     #当前操作环境是用ssh连接的,这里记录客户端ip
SSH_TTY=/dev/pts/1                  #ssh连接的终端时pts/1
USER=root                           #当前登录的用户
..........更多参数可以使用set和env命令查看.............

位置参数变量:

$nn为数字,$0表示当前 Shell 脚本程序的名称,$1-9 代 表 第 一 到 第 九 个 参 数 , 十 以 上 的 参 数 需 要 用 大 括 号 包 含 , 如 如{10}
$*这个变量代表命令行中所有的参数,$把所有的参数看成一个整体
$@这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待
$#这个变量命令行中所有参数的个数

$1 是你给写的shell脚本传的第一个参数,$2是你给你写的shell脚本传的第二个参数

[root@localhost sh]$ vim test.sh
#!/bin/sh
echo "shell脚本本身的名字: $0"
echo "传给shell的第一个参数: $1"
echo "传给shell的第二个参数: $2"

保存退出后,你在Test.sh所在的目录下输入 bash Test.sh 1 2

结果输出:

shell脚本本身的名字: Test.sh
传给shell的第一个参数: 1
传给shell的第二个参数: 2

$ *会把接收的所有参数当成一个整体对待,而$@则会区分对待接收到的所有参数。举个例子:

[root@localhost sh]$ vi parameter2.sh
#!/bin/bash
for i in"$*"
#定义for循环,in后面有几个值,for会循环多少次,注意“$*”要用双引号括起来
#每次循环会把in后面的值赋予变量i
#Shell把$*中的所有参数看成是一个整体,所以这个for循环只会循环一次
	do
		echo "The parameters is: $i"
		#打印变量$i的值
	done
x=1
#定义变量x的值为1
for y in"$@"
#同样in后面的有几个值,for循环几次,每次都把值赋予变量y
#可是Shel1中把“$@”中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
	do
		echo "The parameter$x is: $y"
		#输出变量y的值
		x=$(( $x +1 ))
		#然变量x每次循环都加1,为了输出时看的更清楚
	done

预定义变量:

预定义变量作用
$?最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非О(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。
$$当前进程的进程号(PID)
$!后台运行的最后一个进程的进程号(PID)

先来看看”$?”这个变量,举个例子说明

[root@localhost sh]$ ls
count.sh hello.sh parameter2.sh parameter.sh
#ls命令正确执行
[root@localhost sh]$ echo $?
#预定义变量“$?”的值是0,证明上一个命令执行正确
[root@localhost sh]$ ls install.log
ls:无法访问install.log:没有那个文件或目录
#当前目录中没有install.log文件,所以ls命令报错了
[root@localhost sh]$ echo $?
2
#变量“$?”返回一个非О的值,证明上一个命令没有正确执行
#至于错误的返回值到底是多少,是在编写ls命令时定义好的,如果碰到文件不存在就返回数值2

再来说明下”$ ”和” ”和” !”这两个预定义变量

[root@localhost sh]$ vi variable.sh
#!/bin/bash
echo "The current process is $$"
#输出当前进程的PID.
#这个PID就是variable.sh这个脚本执行时,生成的进程的PID
find /root -name hello.sh &
#使用find命令在root目录下查找hello.sh文件
#符号&的意思是把命令放入后台执行,工作管理我们在系统管理章节会详细介绍
echo "The last one Daemon process is $!"
#输出这个后台执行命令的进程的PID,也就是输出find命令的PID号
只读变量

[root@localhost sh]$ vi readonly.sh
#!/bin/bash
a=10
#语法:readonly 变量名
readonly a
a=20   #会报错readonly variable
echo $a

接受键盘输入
[root@localhost ~]$ read [选项][变量名]
选项:
	-a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符。
	-p: “提示信息”:在等待read输入时,输出提示信息
	-t: 秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间
	-n: 数字:read命令只接受指定的字符数,就会执行
	-s: 隐藏输入的数据,适用于机密信息的输入
    -d: 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志。
    -e: 在输入的时候可以使用命令补全功能。
变量名:
变量名可以自定义,如果不指定变量名,会把输入保存入默认变量REPLY.
如果只提供了一个变量名,则整个输入行赋予该变量.
如果提供了一个以上的变量名,则输入行分为若干字,一个接一个地赋予各个变量,而命令行上的最后一个变量取得剩余的所有字

写个例子来解释下read命令:

[root@localhost sh]$ vi read.sh
#!/bin/bash

read -t 30 -p "Please input your name: " name
#提示“请输入姓名”并等待30 秒,把用户的输入保存入变量name 中
echo "Name is $name"
#看看变量“$name”中是否保存了你的输入

read -s -t 30 -p "Please enter your age: " age
#提示“请输入年龄”并等待30秒,把用户的输入保存入变量age中
#年龄是隐私,所以我们用“-s”选项隐藏输入
echo -e "\n"
#调整输出格式,如果不输出换行,一会的年龄输出不会换行
echo "Age is $age"

read -n 1 -t 30 -p "Please select your gender[M/F]:" gender
#提示“请选择性别”并等待30秒,把用户的输入保存入变量gender
#使用“-n1”选项只接收一个输入字符就会执行(都不用输入回车)
echo -e "\n"
echo "Sex is $gender"

管道符合重定向

在Linux操作系统中,重定向符和管道是非常有用的工具,用于处理命令行中的输入和输出。重定向符允许我们将命令的输入或输出重定向到文件或其他命令,而管道允许我们将一个命令的输出作为另一个命令的输入。

shell运算符

在shell中,运算符和其他编程语言一样,常见的有算数运算符,关系运算符,逻辑运算符,字符串运算符,文件测试运算符等

算数运算符

原始bash不支持简单的数学运算符,但是可以通过其他命令来实现,例如awk 和expr,expr最常用。expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号而不是单引号):

[root@localhost ~]$ vi computer.sh
#!/bin/bash
val=`expr 2 + 2`
echo "两数之和为 : $val"
#注意
#表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
#完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20

|加法 |expr $a + $b 结果为 30。

|减法 |expr $a - $b 结果为 -10。

*| 乘法 |expr $a * $b 结果为 200。

/ |除法 |expr $b / $a 结果为 2。

% |取余| expr $b % $a 结果为 0。

= |赋值| a=$b 将把变量 b 的值赋给 a。

==| 相等。用于比较两个数字,相同则返回 true(真)。| [ $a == $b ] 返回 false(假)。

!= |不相等。用于比较两个数字,不相同则返回 true。 |[ $a != $b ] 返回 true。

[root@localhost ~]$ vi computers.sh
#!/bin/bash
a=10
b=20
echo ' '
echo 'a+b= ' `expr $a + $b`
echo 'a-b= ' `expr $a - $b`
echo 'a*b= ' `expr $a \* $b`
echo 'a/b= ' `expr $a / $b`
echo 'a%b= ' `expr $a % $b`

#判断是否相等
if [ $a == $b ]
then
	echo 'a等于b'
else
	echo 'a不等于b'
fi

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字.
下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

在这里插入图片描述

[root@localhost ~]$ [ 10 -gt 10 ] 
[root@localhost ~]$ echo $? 
 1
[root@localhost ~]$ [ 10 -eq 10 ] 
[root@localhost ~]$ echo $? 
 0

案例:判断当前输入的用户是否存在。如果存在则提示“用户存在”否则提示“用户不存在”。

如果要在shell脚本使用linux命令,可以使用 ( ) 包裹命令例如: d i s k s i z e = ()包裹命令 例如:disk_size= ()包裹命令例如:disksize=(df -h | awk ‘NR==2 {print $5}’)

[root@localhost ~]$ vim demo.sh 
#!/bin/bash
#接受用户的输入
read -p '请输入需要查询的用户名:' username

#获取指定用户名在passwd文件中出现的次数
count=$(cat /etc/passwd | grep $username | wc -l)
#count=`cat /etc/passwd | grep $username | wc -l`

#判断出现的次数,如果次数=0则用户不存在,反之存在
if [  $count == 0 ]
then 
		echo '用户不存在'
	else 
		echo '用户存在'
fi

逻辑运算符

下表常用的布尔运算符,假定变量a为10,变量b为20:
在这里插入图片描述
或运算 : 一个为真即为真,全部为假才是假
与运算: 一个为假即为假,全部为真才是真

字符串运算符

下表列出了常用的字符串运算符,假定变量 a 为 “abc” ,变量b为 “efg”:
在这里插入图片描述

文件测试运算符(重点)

文件测试运算符用于检测 Unix/Linux 文件的各种属性。
在这里插入图片描述

流程控制

if条件判断

单分支if条件

if [ 条件判断式]
then
程序
fi

案例
read -t 6 -p "please input d=?" d
if [ $d = 0]
	then 
		echo "haha $d"
	else 
		echo "not found"
fi			 

多分支if条件语句

语法:

	if [ 条件判断式1 ]
		then
			当条件判断式1成立时,执行程序1
	elif [ 条件判断式2 ]
		then
			当条件判断式2成立时,执行程序2
...省略更多条件...
else
	当所有条件都不成立时,最后执行此程序
fi

case语句语法如下

case $变量名 in
	"值1")
	如果变量的值等于值1,则执行程序1
	;;
	"值2")
	如果变量的值等于值2,则执行程序2
	::
	…省略其他分支…
	*)
	如果变量的值都不是以上的值,则执行此程序
	;;
esac
案例
[root@localhost ~]$ vi sh/if-case.sh
#!/bin/bash
read -p "请输入一个字符,并按Enter确认:" KEY
case "$KEY" in
	[a-z]|[A-Z])
	echo "您输入的是字母"
	;;
	
	[0-9])
	echo "您输入的是数字"
	;;
	
	*)
	echo "您输入的是其他字符"
	;;
esac

for循环

语法1

for 变量 in 值1 值2 值3 …(可以是一个文件等)
	do
		程序
	done
	
	这种语法中for循环的次数,取决于in后面值的个数(空格分隔),有几个值就循环几次,并且每次循环都把值赋予变量。
	也就是说,假设in后面有三个值,for会循环三次,第一次循环会把值1赋予变量,第二次循环会把值2赋予变量,以此类推。
案例
[root@localhost ~]$ vi sh/for.sh
#!/bin/bash
#打印时间

for time in morning noon afternoon evening
	do
		echo "This time is $time!"
	done

语法2

for (( 初始值;循环控制条件;变量变化 ))
	do
		程序
	done
	
语法二中需要注意:
初始值:在循环开始时,需要给某个变量赋予初始值,如i=1;

循环控制条件:用于指定变量循环的次数,如i<=100,则只要i的值小于等于100,循环就会继续;

变量变化:每次循环之后,变量该如何变化,如i=i+1。代表每次循环之后,变量i的值都加1。

案例
[root@localhost ~]$ vi sh/add. sh
#!/bin/bash
#从1加到100

s=0
for (( i=1;i<=100;i=i+1 ))
#定义循环100 次
do
	s=$(( $s+$i ))
	#每次循环给变量s赋值
	done
echo "The sum of 1+2+...+100 is : $s"
#输出1加到100的和

while 循环

对循环来讲,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,
循环才会成立。

语法

while [ 条件判断式 ]
	do
		程序
	done
案例
i=1
s=0
while [$i -le 100]
	do
		s=$(( $s+$i ))
		i =$(( $i +1))
	done
echo "The sum is :$s"

until循环

和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。

until [条件判断式]
	do
		程序
	done

字符串

字符截取,替换命令

cut列提取命令
[root@localhost ~]$ cut [选项] 文件名
选项:
-f 列号: 提取第几列
-d 分隔符: 按照指定分隔符分割列
-n	取消分割多字节字符
-c 字符范围: 不依赖分隔符来区分列,而是通过字符范围(行首为0)来进行字段提取。“n-”表示从第n个字符到行尾;“n-m”从第n个字符到第m个字符;“一m”表示从第1个字符到第m个字符。
--complement	补足被选择的字节、字符或字段
--out-delimiter	指定输出内容是的字段分割符

cut命令的默认分隔符是制表符,也就是“tab”键,不过对空格符可以支持的不怎么好啊。我们先建立一个测试文件,然后看看cut命令的作用吧:

[root@localhost ~]$ vi student.txt
id	name	gender	mark
1	liming	m		86
2	sc		m		67
3	tg		n		90
[root@localhost ~]$ cut -f 2 student.txt
#提取第二列内容
awk 编程
awk 概述

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具

[root@localhost ~]$ printf ‘输出类型输出格式’ 输出内容

输出类型:
%c:     ASCII字符.显示相对应参数的第一个字符
%-ns:   输出字符串,减号“-”表示左对齐(默认右对齐),n是数字指代输出几个字符,几个参数就写几个%-ns
%-ni:   输出整数,n是数字指代输出几个数字
%f:    输出小数点右边的位数
%m.nf:  输出浮点数,m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表共输出8位数,其中2位是小数,6位是整数。

输出格式:
\a: 输出警告声音
\b: 输出退格键,也就是Backspace键
\f: 清除屏幕
\n: 换行
\r: 回车,也就是Enter键
\t: 水平输出退格键,也就是Tab 键
\v: 垂直输出退格键,也就是Tab 键

为了演示printf命令,我们需要修改下刚刚cut命令使用student.txt文件,文件内容如下:

[root@localhost ~]$ vi student.txt
ID      Name    php  	 Linux  	MySQL 	  Average
1       AAA      66         66       66           66
2       BBB      77         77       77           77
3       CCC      88         88       88           88

#printf格式输出文件
[root@localhost ~]$ printf '%s\t %s\t %s\t %s\t %s\t %s\t \n’ $(cat student.txt)
#%s分别对应后面的参数,6列就写6个
ID      Name    php   Linux  MySQL   Average
1       AAA      66         66       66           66
2       BBB      77         77       77           77
3       CCC      88         88       88           88

如果不想把成绩当成字符串输出,而是按照整型和浮点型输出,则要这样:

[root@localhost ~]$ printf '%i\t %s\t %i\t %i\t %i\t %8.2f\t \n’ \ $(cat student.txt | grep -v Name)

awk基本使用
[root@localhost ~]$ awk‘条件1{动作1} 条件2{动作2}…’ 文件名
条件(Pattern):
	一般使用关系表达式作为条件。这些关系表达式非常多,例如:
	x > 10  判断变量x是否大于10
	x == y  判断变量x是否等于变量y
	A ~ B   判断字符串A中是否包含能匹配B表达式的子字符串
	A !~ B  判断字符串A中是否不包含能匹配B表达式的子字符串
	
动作(Action) :
	格式化输出
	流程控制语句

常用参数:

   -F	指定输入时用到的字段分隔符
   -v	自定义变量
   -f	从脚本中读取awk命令
   -m	对val值设置内在限制

我们这里先来学习awk基本用法,也就是只看看格式化输出动作是干什么的。

awk '{printf $2 "\t" $6 "\n"}' student.txt
# 输出第二列和第六列

比如刚刚截取df命令的结果时,cut命令已经力不从心,我们来看看awk命令:

df -h | awk '{print $1 "\t" $3}'
#截取df命令的第一列和第三列
awk的条件

在这里插入图片描述

BEGIN

BEGIN是awk的保留字,是一种特殊的条件类型。BEGIN的执行时机是"在 awk程序一开始时,
尚未读取任何数据之前执行"。一旦BEGIN后的动作执行一次,当awk开始从文件中读入数据
BEGIN的条件就不再成立,所以BEGIN定义的动作只能被执行一次。

[root@localhost ~]$ awk 'BEGIN{printf "This is a transcript \n" } {printf $2 "\t" $6 "\n"}’ student.txt
#awk命令只要检测不到完整的单引号不会执行,所以这个命令的换行不用加入“|”,就是一行命令
#这里定义了两个动作
#第一个动作使用BEGIN条件,所以会在读入文件数据前打印“这是一张成绩单”(只会执行一次)
#第二个动作会打印文件的第二字段和第六字段
END

END也是awk保留字,不过刚好和BEGIN相反。END是在awk程序处理完所有数据,即将结束时执行。END后的动作只在程序结束时执行一次。例如:

[root@localhost ~]$ awk 'END{printf "The End \n"} {printf $2 "\t" $6 "\n"}’ student.txt
#在输出结尾输入“The End”,这并不是文档本身的内容,而且只会执行一次
关系运算符
[root@localhost ~]$ cat student.txt | grep -v Name | awk '$6 >= 87 {printf $2 "\n"}'
#使用cat输出文件内容,用grep取反包含“Name”的行
#判断第六字段(平均成绩)大于等于87分的行,如果判断式成立,则打第六列(学员名$2)

加入了条件之后,只有条件成立动作才会执行,如果条件不满足,则动作则不运行。通过这个实验,大家可以发现,虽然awk是列提取命令,但是也要按行来读入的。这个命令的执行过程是这样的:

1)如果有BEGIN条件,则先执行BEGIN定义的动作。
2)如果没有BEGIN条件,则读入第一行,把第一行的数据依次赋予$0、$1、$2等变量。其中$0代表此行的整体数据,$1代表第一字段,$2代表第二字段。
3)依据条件类型判断动作是否执行。如果条件符合,则执行动作,否则读入下一行数据。如果没有条件,则每行都执行动作。
4)读入下一行数据,重复执行以上步骤。

[root@localhost ~]$ awk '$2 ~ /AAA/ {printf $6 "\n"}' student.txt
#如果第二字段中输入包含有“Sc”字符,则打印第六字段数据
85.66
正则表达式

如果要想让awk识别字符串,必须使用"//"包含,例如

[root@localhost ~]$ awk '/Liming/ {print}’student.txt
#打印Liming的成绩
awk内置变量

在这里插入图片描述

1、打印文件的第一列(域) :
 awk '{print $1}' filename
 
2、打印文件的前两列(域) :
 awk '{print $1,$2}' filename
 
3、打印完第一列,然后打印第二列 : 
awk '{print $1 $2}' filename

4、打印文本文件的总行数 : 
awk 'END{print NR}' filename

5、打印文本第一行 :
awk 'NR==1{print}' filename

6、打印文本第二行第一列 :
sed -n "2, 1p" filename | awk 'print $1'



1. 获取第一列
ps -aux | grep watchdog | awk '{print $1}'

2. 获取第一列,第二列,第三列
ps -aux | grep watchdog | awk '{print $1, $2, $3}'

3. 获取第一行的第一列,第二列,第三列
ps -aux | grep watchdog | awk 'NR==1{print $1, $2, $3}'

4. 获取行数NR
df -h | awk 'END{print NR}'

5. 获取列数NF(这里是获取最后一行的列数,注意每行的列数可能是不同的)
ps -aux | grep watchdog | awk 'END{print NF}'

6. 获取最后一列
ps -aux | grep watchdog | awk '{print $NF}'

7. 对文件进行操作
awk '{print $1}' fileName

8. 指定分隔符(这里以:分割)
ps -aux | grep watchdog |awk  -F':' '{print $1}'

9. 超出范围不报错
ps -aux | grep watchdog | awk '{print $100}'

流程控制
[root@localhost ~]$ cat student.txt
ID      Name    php   Linux  MySQL   Average
1       AAA      66         66       66           66
2       BBB      77         77       77           77
3       CCC      88         88       88           88

我们先来看看该如何在awk中定义变量与调用变量的值。假设我想统计PHP成绩的总分,那么就应该这样:

[root@localhost ~]$ awk 'NR==2 {php1=$3}
NR==3 {php2=$3}
NR==4 {php3=$3;totle=phpl+php2+php3;print "totle php is " totle}’ student.txt
#统计PHIP成绩的总分
我们解释下这个命令。“NR==2 {iphp1=$3}” (条件是NR==2,动作是php1=$3) 这句话是指如果输入数据是第二行(第一行是标题行),就把第二行的第三字段的值赋予变量“php1”。
“NR==3 {php2=$3}" 这句话是指如果输入数据是第三行,就把第三行的第三字段的值赋予变量“php2”。“NR==4 {php3=$3;totle=phpl+php2+php3;print “totle php is " totle}”(“NR==4”是条件,后面(中的都是动作)这句话是指如果输入数据是第四行﹐就把第四行的第三字段的值赋予变量"php3”;然后定义变量totle的值是“php1+php2+php3”;然后输出“totle php is”关键字,后面加变量totle的值。
awk函数
function 函数名(参数列表){
	函数体
}

[root@localhost ~]$ awk 'function test(a,b) { printf a "\t" b "\n"}
#定义函数test,包含两个参数,函数体的内容是输出这两个参数的值
{ test($2,$6) } ' student.txt
#调用函数test,并向两个参数传递值。
Name    Average
AAA      87.66
BBB      85.66
CCC      91.66

sed

入门案例

sort

入门案例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值