22.shell脚本学习

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

原文地址:https://www.cnblogs.com/liuzhanghao/p/12030745.html