1、执行脚本的方式
#!/bin/bash
echo hello world
bash 文件名
解析脚本
bash
会在后台打开一个终端,将结果返回到当前终端
source 文件名
读取脚本信息,并运行
- 在当前终端解析脚本,并把结果返回给当前终端
chmod 777 文件名
给脚本赋予可执行权限
2、shell常用的解析器
bash
,与终端交互性比较好,多用于Linux系统sh
,与终端交互性较好,一般用于开发板
3、修改环境变量
env
终端输入直接查看系统变量
echo $PATH
PATH的作用,包含了执行文件时的默认查找路径,如果文件不在默认查找路径中,就需要添加上路径,比如./a.out
4、修改PATH路径
该PATH过程中不要对原有的路径进行修改
4.1 只对当前终端生效
export PATH=$PATH:/home/ubuntu
export
给系统变量赋值
4.2 只对当前用户生效
修改家目录下的.bashrc
文件
sudo vim ~/.bashrc
在文件的最下方,添加一条export
表达式
export PATH=$PATH:/home/ubuntu
让配置文件生效:
- 重启,永久生效
source ~/.bashrc
. ~/.bashrc
(后两种方式都只能临时生效)
4.3 对所有用户生效
sudo vim /etc/bash.bashrc
在文件的最下方,添加一条export
表达式
export PATH=$PATH:/home/ubuntu/test
让配置文件生效:
- 重启,永久生效
source /etc/bash.bashrc
. /etc/bash.bashrc
(后两种方式都只能临时生效)
另一种方法
修改/etc/environment
,把路径添加到原有内容后面
让配置文件生效:
- 重启,永久生效
source /etc/environment
. /etc/environment
(后两种方式都只能临时生效)
5、shell中的变量
shell中默认都是全局变量
变量名=变量的值
变量名=‘变量的值’
变量名=”变量的值“
注意事项
- = 两边不允许有空格
- 变量的中间值,加空格时,需要使用 ’ ’ 或者 " "
- shell中访问不存在的变量,结果为空值
5.1 访问变量的方式
$变量名 或者 ${变量名}
5.2 修饰变量的关键字
unset #清空变量
readonly #只读变量,不能修改
local #定义局部变量,只能在函数中使用
5.3 位置变量/外部传参
echo $0 $1 $2 $3 ... $n
echo $* #$*获取外部的所有参数,不包括脚本名
echo $@ #$@获取外部的所有参数,不包括脚本名
echo $# #$#获取外部参数的个数,不包括脚本名
6、命令置换符
-
把指令运行的结果值给变量
1.``
2.$()
7、数组
数组名=(初值1 初值2 初值3 ...)
- shell中的数组,用**( )**进行初始化,每一个初始值之间存的是空格
数组名=([下标]=初值1 [下标]=初值2 [下标]=初值3 ...)
- 稀疏数组的下标可以不连续
- 数组成员的赋值
数组名[下标]=90
${数组名[下标]}
- 访问数组中的元素
${#arr[*]} 或者 ${#arr[@]}
- 获取数组中元素的个数
${arr[@]} 或者 ${arr[*]}
- 访问数组内所有元素
8、输入和输出
8.1 echo
echo
打印是会自动换行,且不解析转义字符
echo -n
取消打印时的换行
echo -e "1\n"
加**-e**可以解析转义字符
8.2 read
read 变量名
从终端读取变量
read -s 变量名
不会回显从终端输入的变量
read -p "提示信息" 变量名
终端1读入前输出提示信息
read -t 秒数 变量名
终端输入等待的秒数
read -n 参数个数 变量名
指定个数字符输入
read -a 数组名
从终端输入数组中的元素
9、算术运算
9.1 (())
-
常用于shell中的整数运算
-
(())
几乎支持所有C语言中的复杂运算,支持幂运算(**) -
(())
使用数据时,可以加**$**也可以不加 -
(())
使用数据运算时,运算符两侧可以加空格 -
((表达式1, 表达式2, 表达式3....))
每个表达式都会运行取最后一个表达式的结果
9.2 let
let 变量名=表达式
let
使用变量时,可以加**$**也可以不加let
在进行运算时,运算符两侧不允许加空格let var=a+b
let
支持幂运算(**)和自增(++)自减(–)
9.3 $[]
变量名=$[表达式1, 表达式2, 表达式3...]
每个表达式都执行,取最后一个表达式的结果- 使用变量可以加**$**也可以不加
- 运算符两侧可以有空格也可以没有
- 支持幂运算(**)和自增(++)自减(–)
9.4 expr
expr
是一条指令expr
在运算时,必须给变量加**$**- 运算符两侧必须有空格
- 不支持幂运算和自增自减
- 使用时某些字符需要转义
- 接收
expr
的数据使用**``** match STRING1 STRING2
- 返回string2在string1中匹配的个数
substr STRING POS LENGTH
- 返回从string中第pos个位置开始,截取length长度的字符串
index STRING CHARS
- 返回字符在字符串第一次出现的位置,从位置1开始,如果查找的是多个字符,返回第一次出现的字符位置
length STRING
- 返回字符串长度
expr
的基础算术语法
ARG1 | ARG2 若ARG1的值不为0,则返回ARG1,否则返回ARG2
ARG1 & ARG2 若两边的值都不为0,则返回ARG1,否则返回 0
ARG1 < ARG2 ARG1 小于ARG2
ARG1 <= ARG2 ARG1 小于或等于ARG2
ARG1 = ARG2 ARG1 等于ARG2
ARG1 != ARG2 ARG1 不等于ARG2
ARG1 >= ARG2 ARG1 大于或等于ARG2
ARG1 > ARG2 ARG1 大于ARG2
ARG1 + ARG2 计算 ARG1 与ARG2 相加之和
ARG1 - ARG2 计算 ARG1 与ARG2 相减之差
ARG1 * ARG2 计算 ARG1 与ARG2 相乘之积
ARG1 / ARG2 计算 ARG1 与ARG2 相除之商
ARG1 % ARG2 计算 ARG1 与ARG2 相除之余数
expr
对字符串的惭怍
match STRING1 STRING2
返回string2在string1中完全匹配的个数
substr STRING POS LENGTH
返回从string中的第pos个位置开始,截取length长度的子串
index STRING CHARS
返回字符在字符串中第一次出现的位置,位置从1开始,如果查找的是多个字符,返回的是最小的weizhi
length STRING
返回字符串的长度
将网址分段放入数组
#!/bin/bash
arr=()
i=0
read -p "输入一个网址:" str
#str=www.4399.com
len1=`expr length $str`
head1=`expr index $str .`
arr[$i]=`expr substr $str 1 $[head1-1]`
#arr[1]=www
#str2=4399.com
str2=`expr substr $str $[head1+1] $[len1-head1+1]`
echo $str2
head2=`expr index $str2 .`
len2=`expr length $str2`
arr[$[++i]]=`expr substr $str2 1 $[head2-1]`
arr[$[++i]]=`expr substr $str2 $[head2+1] $[len2-head2]`
echo ${arr[*]}
10、分支结构
10.1 test
#整数运算
a = b a -eq b
a >= b a -ge b
a > b a -gt b
a <= b a -le b
a < b a -lt b
a != b a -ne b
#对字符串操作 在if中使用字符串判断,给字符串加上双引号
-n STRING #判断字符串是否非空
#the length of STRING is nonzero
#STRING equivalent to -n STRING
-z STRING #判断字符串是否为空
#the length of STRING is zero
STRING1 = STRING2 #判断字符串是否相等
#the strings are equal
STRING1 != STRING2 #判断字符串是否不相等
#the strings are not equal
#对文件的相关操作
-r:文件存在并且可读
-w:文件存在并且可写
-x:文件存在并可执行
-s:文件存在并且有内容
-S:文件存在且为套接字文件
-b:文件存在且为块设备文件
-p:文件存在且为管道文件
-L/-h:文件存在且为软链接文件
-f:文件存在并为普通文件
-e:文件存在
file1 -nt file2:1的时间戳比2更新
file1 -ot file2:1的时间戳比2的更旧/2的时间戳更新
10.2 if
#单分支if
if [ test语句 ]
then
语句块
fi
#双分支if
if [ test语句 ]
then
语句块
else
条件不成立执行的语句
fi
#多分支if
if [ test语句 ]
then
语句块
elif
then
条件不成立执行的语句
fi
输入一个文件名,判断是否为shell脚本文件,如果是脚本文件,判断是否有可执行权限,如果有可执行权限,运行文件,如果没有可执行权限,给文件添加可执行权限。
#!/bin/bash
read -p "请输入文件名:" filename
len=`expr length $filename`
head=`expr index $filename .`
tail=`expr substr $filename $[head+1] $[len-head]`
if [ $tail = "sh" ]
then
if [ -x $filename ]
then
bash $filename
else
chmod 777 $filename
fi
else
echo 不是脚本
fi
终端输入两文件名,判断哪一个文件更新
#!/bin/bash
read -p "请输入文件名:" filename1
read -p "请输入文件名:" filename2
if [ $filename1 -nt $filename2 ]
then
echo $filename1更新
else
echo $filename2更新
fi
终端输入用户,判断用户是否存在,如果不存在,添加用户
#!/bin/bash
read -p "输入一个用户名:" name
usrname=`grep ^$name /etc/passwd `
if [ $usrname ]
then
echo 存在此用户
else
sudo adduser $name
fi
终端输入年份,判断闰平年
#!/bin/bash
read -p "输入一个年份:" year
if [ $((year%4)) -eq 0 -a $((year%100)) -ne 0 -o $((year%400)) -eq 0 ]
then
echo "$year是闰年"
else
echo "$year是平年"
fi
10.3 case … in
case ${变量名} in
常量)
语句
;;
常量)
语句
;;
.....
常量n)
语句
esac
#!/bin/bash
read -p "请输入一个变量" var
case $var in
a)
echo "a"
;;
b)
echo "b"
;;
*) #*的功能类似c中的default,defaul的位置可以任意
#*表示通配所有情况,位置不能任意
echo "其他情况"
;;
c)
echo "c"
#;; 最后一个分支可以不加;;
esac
1|2|3|4):符合1-4任一个即可
[1-4][8-9]):符合1-4,和8-9中任一个即可
[0-9]):符合0-9中任一个即可
1):符合1
11、通配符
- *:通配一个或多个字符
- ?:通配一个字符
- []:只能通配[]中的一个字符
- [1-5]:通配1-5内的任意一个字符
- [12345]:通配12345中的任一个字符
- [1,2,3,4,5]:通配方括号中的所有内容
终端输入年分,输出每个月各有多少天
#!/bin/bash
read -p "输入一个年份:" year
read -p "输入一个月份:" month
case $month in
1|3|5|7|8|10|12)
echo "这个月31天"
;;
4|6|9|11)
echo "这个月30天"
;;
2)
if [ $((year%4)) -eq 0 -a $((year%100)) -ne 0 -o $((year%400)) -eq 0 ]
then
echo "这个月29天"
else
echo "这个月28天"
fi
esac
12、循环结构
12.1 while
while [ 条件 ]
do
语句块
done
#!/bin/bash
read var
i=1
j=1
while [ $i -le $var ]
do
j=1
while [ $j -le $i ]
do
echo -n "*"
((j++))
done
echo
((i++))
done
12.2 for
#for语句的三种表达方式
for((表达式1, 表达式2, 表达式3))
do
语句块
done
for 变量名 in 字符串列表
do
语句块
done
执行逻辑:
var变量会循环得到字符串列表,a、b、c、d每一个值,并在赋值结束后进入循环,当每一个字符串都被赋值一次后,退出循环
!#/bin/bash
#求1-100的和
sum=0 #记录求和的结果
#for((i=0;i<=100;i++))
#for i in `seq 1 1 100`
for i in {1..100}
do
((sum+=i))
done
echo $sum
#稀疏数组求和
#!/bin/bash
arr=([0]=90 [3]=100 [7]80)
sum=0
for sum1 in ${arr[*]}
do
((sum+=arr))
done
echo $sum
#判断家目录下的目录文件和普通文件数量
#!/bin/bash
f=0
d=0
for filename in `ls ~ -a`
do
if [ -f ~/$filename ]
then
((f++))
fi
if [ -d ~/$filename ]
then
((d++))
fi
done
echo $f
echo $d
12.3 select…in
select 变量名 in 选项列表
do
语句块
done
执行逻辑:
打印选项列表让用户通过数字选择
1) aa
2) bb
3) c
#?
如果用户不输入,会再打印一次提示的选项列表
ctrl+c结束选项
#!/bin/bash
select var in unix linux wins
do
case $var in
unix)
echo "打开的是unix系统"
;;
linux)
echo "打开的linix系统"
;;
wins)
echo "打开的是wins系统"
;;
esac
done
12.4 辅助控制关键字
- break
break n
可以跳出n层循环break
默认跳出1层循环
- continue
continue n
可以跳出n层本次循环continue
默认跳出一层本次循环
13、函数
function 函数名() 括号中不能放内容
{
函数体
return 返回值
}
- shell函数定义可以加function,也可以不加
- 函数是否有参数,根据调用的形式和函数的实现有关
- 函数是否有返回值,要看具体的函数如何实现
- shell中函数需要先定义后调用,shell中没有函数声明
函数名 参数1 参数2 参数3 ...
函数调用
- 函数内通过位置参数接收参数
$1 $2 ... ${n}
- 函数参数和脚本参数互不影响
- 函数内部使用位置变量,接收的是函数参数
- 函数外部使用位置变量,接收的是脚本参数
- $0只能是脚本名
- 函数返回值只能是**[0-255]**之间的数
- 如果函数需要返回值,只需要在函数内写return
echo $?
可以用于接收函数返回值- **$?**本质是上一条指令的执行结果
local
只能在函数中使用
#函数数组求和
#!/bin/bash
sum=0
function fun()
{
for((i=0; i<len; i++))
do
((sum+=${arr[i]}))
done
}
arr=([0]=50 [1]=70 [2]=80)
len=${#arr[*]}
fun ${arr[*]} len
echo $sum