linuxshell脚本学习笔记:
复制了一下,然后一个一个向过看的时候发现好多啊。然后下面给了链接。学习请看菜鸟教程:https://www.runoob.com/linux/linux-shell-basic-operators.html
变量:
d= `date+%H:%M:%S` 需要用到``反引号
echo "the script end at $d" 使用变量
for file in $(ls /etc) 循环变量
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script" # 这里的花括号可以不加
done
使用一个定义过的变量,只要在变量名前面加美元符号即可:
your_name="qinjx"
echo $your_name
echo ${your_name} # 加不加{}都可以,加上只是为了方便区分
echo "I am good at ${skill}Script" # 这种就需要加上,因为连在一起了
# 只读变量
#!/bin/bash
myUrl="http://www.google.com"
readonly myUrl
myUrl="http://www.runoob.com" # 这个变量名不能再用
# 删除变量
unset variable_name # 变量被删除后不能再次使用。unset 命令不能删除只读变量。
# 变量类型
# 运行shell时,会同时存在三种变量:
1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
# 字符串
str='this is a string'
单引号字符串的限制:
单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
# 双引号
your_name='runoob'
str="Hello, I know you are "$your_name"!
"
echo -e $str
# 双引号的优点:
双引号里可以有变量
双引号里可以出现转义字符
# 字符串拼接
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3
# 获取字符串长度
string="abcd"
echo ${#string} #输出 4
# 提取字符串
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo
# 查找字符串
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4
数组:
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
array_name=(
value0
value1
value2
value3
)
# 读取数组与赋值 ${数组名[index]}
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
valuen=${array_name[n]}
echo ${array_name[@]} # 读取数组全部内容
# 获取数组长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
# 多行注释
:<<'
注释内容...
注释内容...
注释内容...
'
:<<!
注释内容...
注释内容...
注释内容...
!
shell传递参数:
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
$ chmod +x test.sh
$ ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3
$# | 传递到脚本的参数个数 |
---|---|
$* | 以一个单字符串显示所有向脚本传递的参数。 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
echo "Shell 传递参数实例!";
echo "第一个参数为:$1";
echo "参数个数为:$#";
echo "传递的参数作为一个字符串显示:$*";
$ chmod +x test.sh
$ ./test.sh 1 2 3
Shell 传递参数实例!
第一个参数为:1
参数个数为:3
传递的参数作为一个字符串显示:1 2 3
# $* 与 $@ 区别:
相同点:都是引用所有参数。
不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
echo "-- $* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- $@ 演示 ---"
for i in "$@"; do
echo $i
done
# 输出结果:
$ chmod +x test.sh
$ ./test.sh 1 2 3
-- $* 演示 ---
1 2 3
-- $@ 演示 ---
1
2
3
判断:
read -p "please input your score:" a
if ((a<60)); then #这里必须是(())双括号
echo "you didn't pass the exam"
fi
带有else的判断:
read -p "please input your score:" a
if ((a<60)); then #这里必须是(())双括号
echo "you didn't pass the exam"
else
echo "Good,you pass the exam"
fi
带有elif:
read -p "please input your score:" a
if ((a<60)); then #这里必须是(())双括号
echo "you didn't pass the exam"
elif ((a>60)) && ((a<85)); then # &&并且 ||或者
echo "Good,you pass the exam"
else
echo "Good,you score is very hight"
fi
但是就不能使用>, < , = 这样的符号了,要使用 -lt (小于),-gt (大于),-le (小于等于),-ge (大于等于),-eq (等于),-ne (不等于)。
文本判断:
shell 脚本中if还经常判断关于档案属性,比如判断是普通文件还是目录,判断文件是否有读写执行权限等。常用的也就几个选项:
-e :判断文件或目录是否存在
-d :判断是不是目录,并是否存在
-f :判断是否是普通文件,并存在
-r :判断文档是否有读权限
-w :判断是否有写权限
-x :判断是否可执行
使用if判断时,具体格式为: if [ -e filename ] ; then
case语句:
在shell 脚本中,除了用if来判断逻辑外,还有一种常用的方式,那就是case了。具体格式为:
case 变量 in
value1)
command
;;
value2)
command
;;
value3)
command
;;
*)
command
;;
esac
例如:
read -p "please input your score:" n
a = $[$n%2]
case $a in
1)
echo "then number is odd"
;;
0)
echo "the number is even"
;; # 这个东西必须写
esac
循环for:
for 变量名 in 循环的条件; do
command
done
例如:
for i in `seq 1 5`;do
echo $i
done
也可以写成一句话:
for i in `ls`; do echo $i; done 和 for i in `cat test.txt`; do echo $i; done
循环while:
while 条件; do
command
done
例如:
a = 10
while [ $a -ge 1];do
echo "$a"
a = $[$a-1]
done
函数:
-
1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
-
2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。
function 函数名() {
command
}
例如:
function sum(){
sum = $[$1 + $2]
echo $sum
}
sum $1 $2 这里定义的形参
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
# 注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
1. 编写shell脚本,计算1-100的和;
for i in `seq 1 100`;do
sum = $[$i + $sum]
done
echo $sum
2. 编写shell脚本,要求输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到输入正确的数字为止;
n = 0
while [$n -le "1"];do
read -p "please input a number:" a
done
sum = 0
for i in `1 n`;do
sum = $[$i + $sum]
done
echo $sun
3. 编写shell脚本,把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下;
#! /bin/bash
cd /root/
for f in "ls /root/";do
if [-d $f];then
cp -r $f /tmp/
fi
done
4. 编写shell脚本,批量建立用户user_00, user_01, … ,user_100并且所有用户同属于users组;
4. #! /bin/bash
groupadd users
for i in `seq 0 9`; do
useradd -g users user_0$i
done
for j in `seq 10 100`; do
useradd -g users user_$j
done
5. 编写shell脚本,截取文件test.log中包含关键词’abc’的行中的第一列(假设分隔符为”:”),然后把截取的数字排序(假设第一列为数字),然后打印出重复次数超过10次的列;
5. #! /bin/bash
awk -F':' '$0~/abc/ {print $1}' test.log >/tmp/n.txt
sort -n n.txt |uniq -c |sort -n >/tmp/n2.txt
awk '$1>10 {print $2}' /tmp/n2.txt
6. 编写shell脚本,判断输入的IP是否正确(IP的规则是,n1.n2.n3.n4,其中1<n1<255, 0<n2<255,="" 0<n3<255,="" 0<n4<255<="" span="">)。
6. #! /bin/bash
checkip() {
if echo $1 |egrep -q '^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$' ; then
a=`echo $1 | awk -F. '{print $1}'`
b=`echo $1 | awk -F. '{print $2}'`
c=`echo $1 | awk -F. '{print $3}'`
d=`echo $1 | awk -F. '{print $4}'`
for n in $a $b $c $d; do
if [ $n -ge 255 ] || [ $n -le 0 ]; then
echo "the number of the IP should less than 255 and greate than 0"
return 2
fi
done
else
echo "The IP you input is something wrong, the format is like 192.168.100.1"
return 1
fi
}
rs=1
while [ $rs -gt 0 ]; do
read -p "Please input the ip:" ip
checkip $ip
rs=`echo $?`
done
echo "The IP is right!"
tr命令:
tr -c -d -s [“string1_to_translate_from”] [“string2_to_translate_to”] < input-file
-c 用字符串1中字符集的补集替换此字符集,要求字符集为ASCII。
-d 删除字符串1中所有输入字符。
-s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。
input-file是转换文件名。虽然可以使用其他格式输入,但这种格式最常用。
字符范围
指定字符串1或字符串2的内容时,只能使用单字符或字符串范围或列表。
[a-z] a-z内的字符组成的字符串。
[A-Z] A-Z内的字符组成的字符串。
[0-9] 数字串。
octal 一个三位的八进制数,对应有效的ASCII字符。
[O*n] 表示字符O重复出现指定次数n。因此[O*2]匹配OO的字符串。
tr中特定控制字符的不同表达方式
速记符含义八进制方式
a Ctrl-G 铃声 07
Ctrl-H 退格符 10
f Ctrl-L 走行换页 14
Ctrl-J 新行 12
Ctrl-M 回车 15
Ctrl-I tab键 11
v Ctrl-X 30
实例:
将文件file中出现的”abc”替换为”xyz”
# cat file | tr “abc” “xyz” > new_file
【注意】这里,凡是在file中出现的”a”字母,都替换成”x”字母,”b”字母替换为”y”字母,”c”字母替换为”z”字母。而不是将字符串”abc”替换为字符串”xyz”。
2、使用tr命令“统一”字母大小写
(小写 –> 大写)
# cat file | tr [a-z] [A-Z] > new_file
(大写 –> 小写)
# cat file | tr [A-Z] [a-z] > new_file
3、把文件中的数字0-9替换为a-j
# cat file | tr [0-9] [a-j] > new_file
4、删除文件file中出现的”Snail”字符
# cat file | tr -d “Snail” > new_file
【注意】这里,凡是在file文件中出现的’S’,’n’,’a’,’i’,’l’字符都会被删除!而不是紧紧删除出现的”Snail”字符串。
5、删除文件file中出现的换行’
’、制表’ ’字符
# cat file | tr -d “
” > new_file
不可见字符都得用转义字符来表示的,这个都是统一的。
6、删除“连续着的”重复字母,只保留第一个
# cat file | tr -s [a-zA-Z] > new_file
7、删除空行
# cat file | tr -s “
” > new_file
8、删除Windows文件“造成”的’^M’字符
# cat file | tr -d “
” > new_file
或者
# cat file | tr -s “
” “
” > new_file
【注意】这里-s后面是两个参数”
”和”
”,用后者替换前者
9、用空格符 40替换制表符 11
# cat file | tr -s “ 11” “ 40” > new_file
10、把路径变量中的冒号”:”,替换成换行符”
”
# echo $PATH | tr -s “:” “
”
运算符:
Shell 和其他编程语言一样,支持多种运算符,包括:
算数运算符
关系运算符
布尔运算符
字符串运算符
文件测试运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):
两点注意:
表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
+ | 加法 | 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 ] 返回 true。 |
== | 相等。用于比较两个数字,相同则返回 true。 | [ $a == $b ] 返回 false。 |
关于echo:
#!/bin/sh
echo -e "OK! c" # -e 开启转义 c 不换行
echo "It is a test"
OK! It is a test
# 定向输出
echo "It is a test" > myfile
# 原字符串输出可以使用单引号
echo '$name"'
$name"
# 显示执行结果
echo `date` 反引号
printf:
printf "%-10s %-8s %-4s
" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f
" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f
" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f
" 郭芙 女 47.9876
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99
%s %c %d %f都是格式替代符
%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中.2指保留2位小数。
test:
菜鸟教程
# 代码中的 [] 执行基本的算数运算,如
num1=$[2*3]
num2=$[1+5] # 不能有空格
if test $[num1] -eq $[num2] # test,后面的[]里面没有空格
then
echo '两个数字相等!'
else
echo '两个数字不相等!'
fi
a=10
b=20
if [ $a == $b ] # 必须有空格
then
echo "a 等于 b"
elif [ $a -gt $b ]
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi