【shell】shell基础

一、什么是shell?

shell是处于用户和Linux系统之间的命令解释器。


二、shell基础操作

1.创建shell脚本

vi first_shell.sh

2.shell脚本的格式

#!/bin/bash
#filename:first_shell
#created day:2019.9.28
echo "Hello World!"

第一行:#!/bin/bash

#!是一种约定标记,他告诉系统这个脚本需要用/bin/bash解释器来执行,如果不写这一行脚本也可以执行,只是系统会根据自身的shell解释器来解释脚本。

第二和第三行

shell脚本使用#来标识注释。

第四行:echo “Hello World!”

shell将没有#标识的语句解释为命令。

shell脚本的命令语句可以在行末使用;表示结束,也可以不适用,但是一行有多条语句必须使用;分隔。

3.执行脚本

/bin/bash first_shell.sh

输出结果:

Hello World!

三、变量

1.局部变量

在这里插入图片描述

shell中没有特别标注的变量都属于局部变量,如:

#!/bin/bash
#by goulandis 2019.9.28
A="asd"
echo $A
A=123
echo $A

局部变量只能在脚本内部才能使用。

shell是非类型的解释型语言,变量的类型在运行事确定。

字符串也可以不要使用"",如:A=asd,输出结果也是一样的,但是不使用""赋值时,字符串之间不能出现空格,如:A=a s d这样赋值会报错。

输出结果:

asd
123

变量的使用

shell中直接使用$加变量名的组合即可使用变量,如:echo $A

需要注意的是:在给变量赋值时不能出现空格,如:A = 123,这样的语法shell无法识别,必须为:A=123,才可以。

在这里插入图片描述
在这里插入图片描述

2.环境变量

环境变量可以在脚本内也可以在其他的脚本中使用,即在系统环境中都可以使用。

变量名作用
$0存储当前脚本的名字
$nn是一个数字,存储传递给脚本的迪n个变量
$#存储传递给脚本的参数的数量
$*存储传递给脚本的所有的参数
$@用法和$*一样//
$?存储上一个命令的退出状态,命令执行成功返回0,否则返回错误码
$$存储当前shell脚本所在进程的ID
$UID存储当前用户ID
$PWD存储当前所在路径

示例:

在这里插入图片描述

在这里插入图片描述

注:

echo -e "\033[32m"

可以修改其后的输出字体的颜色。

echo -e "\033[0m"

结束字体颜色修改。

字体设置详情请前往:https://blog.csdn.net/andylauren/article/details/60873400

输出时可以使用\来进行字符转义

3.变量的命名规则

shell的变量的命名规则基本和C是一致的,并且shell大小写敏感。


四、语句结构

1.if条件语句

普通结构

if((num1>num2))
then
echo "$num1>$num2"
else
echo "$num1<$num2"
fi

和其他语言不同的是,shell中条件判断分支语句不能为空,即不能出现如下情况:

if((num1>num2))
then
echo "$num1>$num2"
else
fi

如此编译将无法通过。

这里有几点须要注意:

  • if后面更的必须是双括号(()),使用单括号会报错,使用(())变量可以直接使用变量名来使用,而不需要通过 来 引 用 , 除 此 之 外 , i f 后 面 也 可 以 跟 [ ] , 但 是 [ ] 与 变 量 之 间 必 须 使 用 空 格 隔 开 , [ ] 与 i f 也 必 须 使 用 空 格 分 隔 , 且 使 用 [ ] 需 要 使 用 来引用,除此之外,if后面也可以跟[],但是[]与变量之间必须使用空格隔开,[]与if也必须使用空格分隔,且使用[]需要使用 if[][]使[]if使使[]使来引用变量,否则也会报错;

使用双括号:**

a=10
b=20
if((a>b))
then
	echo "$a > $b"
else
	echo "$a < $b"
fi

使用中括号(不使用空格分隔):
在这里插入图片描述
这里有一个错误,即if[a>b]应该改为if[ a > a> a>b]。
使用中括号(使用空格分隔):

在这里插入图片描述

  • 一行中的多条语句须要使用;进行分隔;如:

    if((num1>num2));then
    echo "$num1>$num2"
    fi
    
  • if语句必须使用fi进行结尾,告知解释器if语句的结束;

嵌套结构

#!/bin/bash
#by goulandis 2019.9.29

if [[ $1 -gt 90 ]];then
	echo "every good"
elif [[ $1 -gt 80 ]];then
	echo "good"
elif [[ $1 -gt 60 ]];then
	echo "pass"
else
	echo "no pass"
fi

这里须要注意,每一个if和elif语句后面都必须跟一个then。

逻辑运算符

shell中除了可以使用“+,-,*,/,%,^,>,>=,==,<,<=,!”等编程常用的运算符外,还可以使用字母代替部分运算符。

运算符作用
-f判断文件是否存在 eg: if [ -f filename ]
-d判断目录是否存在 eg: if [ -d dir ]
-eq等于,整型比较
-ne不等于,整型比较
-lt小于,整型比较
-gt大于,整型比较
-le小于或等于,整型比较
-ge大于或等于,整型比较
-a逻辑与 eg: 逻辑表达式 -a 逻辑表达式
-o逻辑或 eg: 逻辑表达式 -a 逻辑表达式
-z空字符串

如向文件中写入内容:

在这里插入图片描述

第一次执行/bin/bash var.sh asd:创建文件text.txt并向文件中写入传入的第一个参数内容;

第二次执行/bin/bash var.sh asd:文件已存在,所以直接cat文件内容。

(())、[]、[[]]的区别

在写shell脚本时,常碰到(())、[]、[[]],这里来看看三者之间的区别:

符号区别
(())(())的作用基本和let一致,(())主要用于算术运算,比较适合进行整数比较,可以直接通过变量名来引用变量,而不需要通过$,只可以使用数学运算符“>,<,==”等进行比较;
[][]的作用与test一致,[]不支持数学运算符,只能使用字符运算符“-ge,-lt”等,[]支持“和!=”,但是“”,“!=”在[]中只能用于字符串的比较;
[[]][[]]的功能比[]要强大,[[]]的用法和[]一样,但是[[]]支持逻辑组合“&&,||”

小知识:

  • 用反引号包含的语句可以当作命令解释。如:

在这里插入图片描述

shell解释器会将反引号内的字符串解释为一个命令(如果命令有效则执行,如果无效则报错),而不是当作字符串。

组合与&&不止可以组合逻辑表达式,还可以组合命令语句,并且组合命令语句时,当前面的语句执行失败,后面的语句将不执行。而组合或||则是无论前面的语句是否执行成功都会执行后面的语句。

2.for循环

普通结构

j=0
for((i=1;i<=100;i++))
do
	j=`expr $i + $j`
done
echo $j

输出结果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
5050

小知识:

  • 这里的循环语句使用的是j=`expr $i + $j`,因为必须告知解释器要将expr $i + $j解释为命令,否则解释器会将expr $i + $j当作是字符串。
  • expr命令的作用是求两个数的和。
  • 在执行脚本时,添加参数-x可以查看脚本运行的过程,如:/bin/bash -x var.sh

for in结构

cd /home/goulandis/shell/tmp
dir=/home/goulandis/shell
for file in $(ls *)
do
	mv $file $dir 
done

file的值从$(ls *)中依次获取,$file即获取file的值; 循环语句放在do和done之间

for in结构的好处在于,可以从一个命令的输出集合里自动读取集合里的数据。、

‘’、""的区别

两者都是为了解决字符串中间有空格的情况,''剥夺了字符串的所有含义,在''内的任何字符都只被解释为字符,而""则保留了一些参数如:$、``、\。

小知识:

  • $(ls *)可以获取当前目录下的所有文件
  • $(ls split*)可以获取当前目录下的所有子目录

3.while循环

while read line
do
	echo $line	
done < /home/goulandis/shell/var.sh

i=0

while ((i<5))
do
	echo $i
	((i++))	
done

输出语句:

#!/bin/bash
#by goulandis 2019.9.28

while read line
do
echo $line
done < /home/goulandis/shell/var.sh

i=0
while ((i<5))
do
echo $i
((i++))
done
0
1
2
3
4
  • while之后可以跟命令语句(如:reas line),也可以更逻辑表达式(如:i<5),但是逻辑表达式必须使用(())括起来,并且while的递增变量也必须使用(())括起来。
  • for一样,while的循=循环体必须放在do done之间。

小知识:

  • read命令配合< 文件名可以读取文件里的内容。如:读取host.txt文件的第二列的内容

    文件内容:

1 Alian man 176
2 Goulandis faleman 168
3 Dekes man 188

​ 操作代码:

while read line
do
	name=`echo $line | awk '{print $2}'`
	echo -e "\033[32mName:$name\033[0m"
done <host.txt

​ 读取结果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
Name:Alian
Name:Goulandis
Name:Dekes

4.until循环

i=5
until [[ i -lt 0 ]]
do
	echo $i
	((i--))
done

输出结果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
5
4
3
2
1
0

while当满足条件时执行不同的是,until是当满足条件时退出;

和所有循环体一样,until的循环体也放在do done中。

5.case条件语句

case $1 in
	apache)
	echo "Install Apache"
	;;
	mysql)
	echo "Install mysql"
	;;
	php)
	echo "Install php"
	;;
	*)
	echo "usage:{$0 apache|mysql|php|help}"
	;;
esac 
  • case语句必须使用esac标识语句结束
  • 每一个分支的匹配值后面是必须跟一个)
  • 每一个分支也必须使用;;进行分隔
  • 不像C++中的switch语句没有break不跳出而继续向下执行,shell中的case语句执行完分支后会自动跳出
  • *表示当分支中没有能比配的值时,就匹配*这个分支

6.select语句

select语句的主要功能就是自动生成一个选择菜单

PS3="select application number:"

select i in "apache" "mysql" "php"
do
	case $i in
		apache)
		echo "install apache"
		;;
		mysql)
		echo "install mysql"
		;;
		php)
		echo "install php"
		;;
		*)
		echo "usage:{input 1|2|3|help}"
	esac
done

输出结果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
1) apache
2) mysql
3) php
select application number:1
install apache

  • in后面可以跟一系列的键值集合,每个键值之间使用空格分隔
  • shell预定义了变量PS3(大写的PS3)用于输入描述,如:输出结果中的select application number:
  • selectcase搭配能形成十分友好的选择界面
  • select的语句体也必须放在do done中间

五、数组

1.一维数组

数组定义

A=(1 2 3)

数组使用

echo ${A[0]}

shell的数组也是从0号索引开始

几种数组的常用方法

方法作用
${A[@]}或${A[*]}显示所有元素
${#A[@]}统计数组的参数个数
${A[@]/1/a}替换数组元素
unset A[n]删除数组中第n个元素

数组的赋值

直接初始化时赋值

A=(
	apache
	mysql
	php
)

一个元素一个元素的赋值

#A=()可写也可不写
A=()
A[0]=0
A[1]=1

六、函数

函数定义

function command()
{
#函数体
}

函数调用

command 参数列表

参数列表按顺序依次对应$1,$2,$3等,如:

function command()
{
	if [[ (! -z $1) && (! -z $2) ]]
	then
		echo $1 $2
	fi
}

command param1 param2

输出结果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
param1 param2

这里要注意使用&&时一个逻辑表达式需要用()括起来,否则&&会将$1进行&&运算。

函数的返回值

函数用return来返回值,但是return只能用于返回整型,返回字符串需要用echo。如:

#返回数字-方法1
function command()
{
	if(($1==1));then
		return $1
	else
		echo $1
	fi
}
command 1
echo $?
#返回数字-方法2
echo $command 1
#返回字符串-方法1
echo $(command asd)
#返回字符串-方法2
echo `command sdf`

输出结果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
1
1
asd
sdf

$?接收上一句命令的返回值。

小知识:

read -p "输入描述" cmd命令可以记录命令命令行的输入到cmd变量中,如:

goulandis@ubuntu:~/shell$ read -p "Input parameter:" cmd
Input parameter:this a command
goulandis@ubuntu:~/shell$ echo $cmd
this a command


七、shell命令

1.sed命令

示例:对如下sed.txt文件进行修改

#by auther 2019.9.30 txt

ip 192.168.9.120
ip 192.168.5.5
ip 168.1.2.111

those my ip

替换字符串

sed -i 's/auther/goulandis/g' sed.txt

输出结果:

#by goulandis 2019.9.30 txt
 
ip 192.168.9.120
ip 192.168.5.5
ip 168.1.2.111

those my i

sed.txt中的所有auther字符串替换成字符串goulandis,其中开头的s和结尾的g是必须写的,这是固定格式,并且参数-i也是必须写的,如果不使用参数-ised只会修改缓冲区中的数据,而不会修改sed.txt源文件中的内容。

在行首/行尾插入

sed -i 's/^/&line /g' sed.txt

输出结果:

line #by goulandis 2019.9.30 txt
line 
line ip 192.168.9.120
line ip 192.168.5.5
line ip 168.1.2.111
line 
line those my ip

sed.txt的每行行首插入字符串line,行首匹配规则使用的是正则表达式,若需要在行尾插入,命令为sed -i 's/$/&字符串/g' sed.txt

在前一行或后一行插入

sed -i '/192.168.9.120/a line ip 192.168.9.9' sed.txt

输出结果:

line #by goulandis 2019.9.30 txt
line 
line ip 192.168.9.120
line ip 192.168.9.9
line ip 192.168.5.5
line ip 168.1.2.111
line 
line those my ip

sed.txt192.168.9.120所在行的后面一行插入字符串line ip 192.168.9.9,这里要注意,这个命令不再写前面的s和后面的g,如果要在前面一行插入,则将a替换成i

打印固定行数的内容

sed -n '1,3p' sed.txt

输出结果:

line #by goulandis 2019.9.30 txt
line 
line ip 192.168.9.120

打印sed.txt中第一行到第三行的内容,其中p是必须写的 ,打印首行和尾行sed -n '1p;$p' sed.txt

这里要注意,'1,$p'表示从首行到尾行,有多行,'1p;$p'表示首行和尾行,只有两行。

2.find命令

寻找文件

find . -name "sed.txt"

在当前目录下寻找文件sed.txt

find . -maxdepth 1 -name "sed.txt"

在当前目录一级目录下搜索sed.txt文件,即不向子目录搜索。

find . -maxdepth 1 -type f -name "*.txt" -mtime -1

在当前目录一级目录下搜索类型为文件,修改时间为1天前的txt文件。

find . -maxdepth 1 -type f -name "*.txt" -mtime -1 -exec rm -rf {} \;

在当前目录一级目录下搜索类型为文件,修改时间为1天前的txt文件并删除这些文件。-exec表示将前面搜索到的内容放到{}中。其中\;是必须的固定格式。-xargs的作用和-exec基本一样,只是-xargs不能配合cpmv命令使用。

3.grep命令

搜索固定内容的行

grep "ip" sed.txt

输出结果:

line ip 192.168.9.120
line ip 192.168.9.9
line ip 192.168.5.5
line ip 168.1.2.111
line those my ip

使用参数-v表示反义,如:grep -v "ip" sed.txt,表示搜索不包含ip的行。-n可以将行号一并打印出来。

grep "120$" sed.txt

搜索以120结尾的行,开头使用"^line"""中写入正则表达式,即可按正则表达式来搜索内容。

4.awk命令

打印列

awk '{print "注解:" $1}' sed.txt

打印第一列的内容,列之间需要用空格分隔,否则将识别成一列,$n表示第n列。$NF表示最后一列,""中可以在输出内容前添加任何注解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值