【Linux】shell快速入门

参考链接: https://www.cnblogs.com/linuxk/p/10495887.html
https://www.jb51.net/article/186296.htm#_label14
https://www.jb51.net/article/161028.htm
仅作学习记录使用~

1、何为shell?与linux命令行有什么区别?

shell翻译成壳的意思,它是包裹在linux内核外层的,一个可通过一系列的linux命令对操作系统发出相关指令的人机界面

shell可以通过其条件语句和循环语句等,把一系列linux命令结合在一起,形成一个相当于面向过程的程序——shell脚本(shell script)来实现一些较为复杂的功能。

  • 总结
    ​ Shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序,用户每输入一条命令,Shell就解释执行一条。Shell存在于操作系统的最外层,负责和用户直接对话,把用户的输入解释给操作系统,并处理各种各样的操作系统输出结果 ,然后输出到屏幕返回给用户。
    而Shell脚本就是命令或程序语句不在命令行下执行,而是通过一个程序文件来执行。

  • 注意
    直接在命令行执行 就是在当前的shell环境下执行 比如涉及到一些环境变量的时候 必须在当前shell环境里执行。
    在脚本里执行的话 脚本执行的时候 会fork一个子进程 所有操作都在子进程进行 如果涉及到一些在脚本里设置环境变量的东西 脚本结束了 环境变量也就消失了。
    这个修改环境变量的话,需要特别注意下。

1.1 环境

shell编程跟java、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。

  • OS
    当前主流的操作系统都支持shell编程,本文档所述的shell编程是指Linux下的shell,讲的基本都是POSIX标准下的功能,所以,也适用于Unix及BSD(如Mac OS)。

  • Linux
    Linux默认安装就带了shell解释器。

  • Mac OS
    Mac OS不仅带了sh、bash这两个最基础的解释器,还内置了ksh、csh、zsh等不常用的解释器。

  • Windows上的模拟器
    windows出厂时没有内置shell解释器,需要自行安装,为了同时能用grep, awk, curl等工具,最好装一个cygwin或者mingw来模拟linux环境。
    cygwin
    mingw

1.2 脚本解释器

  • sh
    即Bourne shell,POSIX(Portable Operating System Interface)标准的shell解释器,它的二进制文件路径通常是/bin/sh,由Bell Labs开发。
    本文讲的是sh,如果你使用其它语言用作shell编程,请自行参考相应语言的文档。

  • bash
    Bash是Bourne shell的替代品,属GNU Project,二进制文件路径通常是/bin/bash。业界通常混用bash、sh、和shell,比如你会经常在招聘运维工程师的文案中见到:熟悉Linux Bash编程,精通Shell编程。

在CentOS里,/bin/sh是一个指向/bin/bash的符号链接:

[root@centosraw ~]# ls -l /bin/*sh

-rwxr-xr-x. 1 root root 903272 Feb 22 05:09 /bin/bash

-rwxr-xr-x. 1 root root 106216 Oct 17 2012 /bin/dash

lrwxrwxrwx. 1 root root   4 Mar 22 10:22 /bin/sh -> bash

但在Mac OS上不是,/bin/sh和/bin/bash是两个不同的文件,尽管它们的大小只相差100字节左右:

iMac:~ wuxiao$ ls -l /bin/*sh

-r-xr-xr-x 1 root wheel 1371648 6 Nov 16:52 /bin/bash

-rwxr-xr-x 2 root wheel  772992 6 Nov 16:52 /bin/csh

-r-xr-xr-x 1 root wheel 2180736 6 Nov 16:52 /bin/ksh

-r-xr-xr-x 1 root wheel 1371712 6 Nov 16:52 /bin/sh

-rwxr-xr-x 2 root wheel  772992 6 Nov 16:52 /bin/tcsh

-rwxr-xr-x 1 root wheel 1103984 6 Nov 16:52 /bin/zsh

1.3 高级编程语言

理论上讲,只要一门语言提供了解释器(而不仅是编译器),这门语言就可以胜任脚本编程,常见的解释型语言都是可以用作脚本编程的,如:Perl、Tcl、Python、PHP、Ruby。Perl是最老牌的脚本编程语言了,Python这些年也成了一些linux发行版的预置解释器。

编译型语言,只要有解释器,也可以用作脚本编程,如C shell是内置的(/bin/csh),Java有第三方解释器Jshell,Ada有收费的解释器AdaScript。

如下是一个PHP Shell Script示例(假设文件名叫test.php):

#!/usr/bin/php

<?php

for ($i=0; $i < 10; $i++)

    echo $i . "\n";

执行:

/usr/bin/php test.php

或者:

chmod +x test.php

./test.php

2. shell脚本的结构

在Linux系统中,Shell脚本通常是使用Vim编辑器进行编写,其内容大多数是命令和程序结构控制语句以及注释构成。其规范的格式如下:

  • Shell脚本的第一行 为 指定脚本解释器,通常为:
#!/bin/bash   或    #!/bin/sh
  • Shell脚本添加版本和个人信息
# Date:  2019-03-08  15:30
# Author: KIM
# Description: nginx_log_cut
# Version: 1.1

Shell脚本中尽量不使用中文
Shell脚本的命名应该以.sh为扩展名
Shell脚本应该放在固定的路径下,如/server/scripts
使用合适的代码缩进规范

2.1 示例代码

#!/bin/sh

cd ~

mkdir shell_tut

cd shell_tut

for ((i=0; i<10; i++)); do

    touch test_$i.txt

done

示例解释
•第1行:指定脚本解释器,这里是用/bin/sh做解释器的(“#!”是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行。)
•第2行:切换到当前用户的home目录
•第3行:创建一个目录shell_tut
•第4行:切换到shell_tut目录
•第5行:循环条件,一共循环10次
•第6行:创建一个test_1…10.txt文件
•第7行:循环体结束

cd, mkdir, touch都是系统自带的程序,一般在/bin或者/usr/bin目录下。for, do, done是sh脚本语言的关键字。

运行Shell脚本有两种方法:

  • (1)作为可执行程序
chmod +x test.sh # 将脚本文件的属性改为可执行的
./test.sh

注意,一定要写成./test.sh,而不是test.sh,运行其它二进制的程序也一样,直接写test.sh,linux系统会去PATH里寻找有没有叫test.sh的,而只有/bin, /sbin, /usr/bin,/usr/sbin等在PATH里,你的当前目录通常不在PATH里,所以写成test.sh是会找不到命令的,要用./test.sh告诉系统说,就在当前目录找

通过这种方式运行bash脚本,第一行一定要写对,好让系统查找到正确的解释器。

这里的"系统",其实就是shell这个应用程序(想象一下Windows Explorer),但我故意写成系统,是方便理解,既然这个系统就是指shell,那么一个使用/bin/sh作为解释器的脚本是不是可以省去第一行呢?是的。

  • (2)作为解释器参数
    这种运行方式是,直接运行解释器,其参数就是shell脚本的文件名,如:
/bin/sh test.sh

/bin/php test.php

这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。

2.2 注释

“# ”开头的就是注释,被编译器忽略

  • 单行注释: #
  • 多行注释: :<<EOF … EOF 或者 :<<! … ! (:<< 标识多行注释开始,并指定一个标识符作为开始结束的标志)

3. shell的变量

变量的类型:环境变量(全局变量)和普通变量(局部变量)

  • 环境变量:也可称为全局变量,可在创建他们的shell及其派生出来的任意子进程shell中使用,环境变量又可分为自定义环境变量bash的内置环境变量
  • 普通变量:也可称为局部变量,只能在创建他们的shell函数或者shell脚本中使用,普通变量一般由开发者在开发脚本程序时创建。

3.1 自定义环境变量

如果想要设置环境变量,就要在给变量赋值之后或在设置变量时用export命令。除了export命令,带-x选项的declare内置命令也可以完成同样的功能(注意:此处不要在变量名前加$)

exprot命令和declare命令的格式如下:

  • ①export 变量名=value
  • ②变量名=value; export 变量名
  • ③declare -x 变量名=value
[root@localhost ~]# export NAME=long
[root@localhost ~]# echo $NAME
long
[root@localhost ~]# declare -x NAME=li
[root@localhost ~]# echo $NAME
li
[root@localhost ~]# NAME=ing;export NAME
[root@localhost ~]# echo $NAME
ing

3.2 普通变量

定义方式有3种:

  • 变量名=value #赋值时不加引号
  • 变量名=‘value’ #赋值时加单引号
  • 变量名=“value” #赋值时加双引号

注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。

  • 除了显式地直接赋值,还可以用语句给变量赋值,如:
for file in `ls /etc`

使用变量

  • 使用一个定义过的变量,只要在变量名前面加美元符号即可;
  • 变量名外面的花括号是可选的,加不加都行(建议加上),加花括号是为了帮助解释器识别变量的边界
your_name="qinjx"

echo $your_name

echo ${your_name}

定义脚本退出状态码

  • exit: 退出脚本
  • exit #

如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码;

测试脚本是否有语法错误:

  • bash -n 脚本
  • bash -x 脚本:单步执行

3.2.1 字符串

字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了,哈哈),字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似。

单引号

str='this is a string'

单引号字符串的限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
  • 单引号字串中不能出现单引号(对单引号使用转义符后也不行)

双引号

str="Hello, I know your are \"$your_name\"! \n"

•双引号里可以有变量
•双引号里可以出现转义字符

3.2.1.1 字符串操作

(1)拼接字符串

your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"

echo $greeting $greeting_1

(2)获取字符串长度:

string="abcd"
echo ${#string} #输出:4

(3)提取子字符串

string="alibaba is a great company"

echo ${string:1:4} #输出:liba

(4)查找子字符串

string="alibaba is a great company"

echo `expr index "$string" is` #输出:8,这个语句的意思是:找出单词is在这名话中的位置

3.3 位置参数变量

在Shell中存在一些特殊的位置参数变量,当我们在命令行、函数或脚本执行时传递参数时,此时就需要使用位置参数变量。如下表:
在这里插入图片描述

3.4 状态变量

在这里插入图片描述

4. 条件测试和比较

4.1 条件测试常用的语法形式

  • test <测试表达式>
  • [ 测试表达式 ]:[]内两端需要有空格
  • [[ 测试表达式 ]]:两端需要有空格,与[]和test的区别在于,在[[]]中可以使用通配符等进行模式匹配;并且与&&、||、>、<等操作符可用于[[]]中,但不能用于[]中,在[]中一般使用 -a、-o、-gt(用于整数)、-lt。除了使用通配符的功能之外,建议放弃该用法。
  • ((测试表达式)):一般用于if语句里,两端不需要空格

示例:

[root@localhost ~]# test -f file && echo ture || echo false
false
表示如果file文件存在,则输出true,否则输出false。

[root@localhost ~]# [ -f /etc/passwd ] && echo 0 || echo 1
0
表示如果/etc/passwd文件存在,则输出0,否则输出1

[root@localhost ~]# [[ -f /etc/passwd && -d /123/ ]] && echo 0 || echo 1
1
表示如果/etc/passwd文件存在,并且/123/目录也存在,则输出0,否则输出1

4.2 文件测试表达式的用法

常用的文件测试操作符:

  • -d:文件存在且为目录则为真,即测试表达式成立
  • -f:文件存在且为普通文件则为真,即测试表达式成立
  • -e:文件存在则为真,即测试表达式成立
  • -r:文件存在且可读则为真,即测试表达式成立
  • -w:文件存在且可写则为真,即测试表达式成立
  • -x:文件存在且可执行为真,即测试表达式成立
  • -s:文件存在且文件大小不为0,即测试表达式成立

tips:测试文件的读、写、执行属性,不光是看文件属性rwx的表示进行判断,还需要看当前执行测试的用户是否真的可以按照对应的权限操作该文件。

特殊条件测试表达式案例

以下写法适用于所有的条件测试表达式,是工作中比较常用替代if语句的方法。判断条件测试表达式的条件成立与否,还需要继续执行多条命令语句的语法形式如下:

[ 条件1 ] && {

COMMAND 1
COMMAND 2
COMMAND 3

}

[[ 条件1 ]] && {

COMMAND 1
COMMAND 2
COMMAND 3

}

test 条件1 && {

COMMAND 1
COMMAND 2
COMMAND 3

}

相当于if语句:

if [ 条件1 ]
then

COMMAND 1
COMMAND 2
COMMAND 3

fi

4.3 字符串测试表达式

字符串测试操作符:

  • -n “字符串”:若字符串的长度不为0,则为真,即测试表达式成立。
  • -z “字符串”:若字符串的长度为0,则为真,即测试表达式成立。
  • “串1” = “串2”:若串1等于串2,则为真,即测试表达式成立,可用==代替=
  • “串1” != “串2”:若串1不等于串2,则为真,即测试表达式成立,可用!==代替!=

tips:字符串比较时等号两边需要空格,没有空格会导致逻辑错误。

4.4 整数二元比较操作符

[]和test中使用		在(())[[]]中使用
-eq						== 或 =
-ne						!=
-gt						>
-ge						>=
-lt						<
-le						<=

4.5 逻辑操作符

[]和test中使用			在(())[[]]中使用
-a							&&
-o							||
!							!

5. If条件语句

条件语句语法:

单分支if语句
if 判断条件; then
  statement1
  statement2
  ...
fi

双分支的if语句:
if 判断条件; then
	statement1
	statement2
	...
else
	statement3
	statement4
	...
fi

多分支的if语句:
if 判断条件1; then
  statement1
  ...
elif 判断条件2; then
  statement2
  ...
elif 判断条件3; then
  statement3
  ...
else
  statement4
  ...
fi

6. case语句

case条件语句相当于多分支的if/elif/else条件语句,但是它比这些条件语句看起来更规范更公正,常被应用于事先系统服务启动脚本等企业应用场景中

​ 在case语句中,程序会将case获取的变量的值与表达式部分的值1、值2、值3等逐个进行比较,如果获取的变量值和某个值(例如值1)相匹配,就会执行值后面对应的指令,直到执行到双分号;;才会停止,然后再跳出语句主体,执行case语句后面的其他指令

如果没有找到匹配变量的任何值,则执行"*)"后面的指令(通常是给使用提示),直到遇到双分号;;或esac结束,这部分相当于if多分支语句中最后的else语句部分。

case语句语法:选择结构
SWITCH为变量的值,对变量的值进行引用,并进行判断选择

case SWITCH in 
value1)
  statement
  ...
  ;;
value2)
  statement
  ...
  ;;
*)
  statement
  ...
  ;;
esac

范例1:根据用户的输入判断用户输入的是哪个数字,如果是1-9的任意数字,则输出对应的数字;如果是其他数字及字符,则返回输入不正确的提示并退出程序。
[root@localhost ]# vim num.sh 
#!/bin/bash
while :;do
read -p "please input your number:" A
case $A in
1)
	echo "You input the number is 1."
	;;
[2-9]*)
	echo "You input then number is $A ."
	;;
q|Q)
	echo "quiting ..."
	exit 0
	;;
*)
	echo "Your input is error.please input your number again."
	;;
esac
done

范例2:给出水果列表,并输出客户选择的水果,且用不同的颜色显示不同的水果。
#!/bin/bash
cat << EOF
1. apple
2. pear
3. banana
4.cheery
EOF
while :;do
read -p "Do you have some fruits." FRUITS
case $FRUITS in 
1)
	echo -e "\033[31mapple\033[0m"
	;;
2)
	
	echo -e "\033[32mpear\033[0m"
	;;
3)
	
	echo -e "\033[37mbanana\033[0m"
	;;
4)
	
	echo -e "\033[36mcherry\033[0m"
	;;
*)
	echo "Your choice is error."
	exit 1
	;;
esac
done

范例3:给输出的字符加颜色基础知识
在linux脚本中,可以通过echo-e参数,结合特殊的数字给不同的字符加上颜色并显示。
内容的颜色可以用数字表示,范围为30-37,每个数字代表一种颜色,代码如下:
echo -e "\033[30m 黑色字体 long \033[0m"
echo -e "\033[31m 红色字体 long \033[0m"
echo -e "\033[32m 绿色字体 long \033[0m"
echo -e "\033[33m 棕色字体 long \033[0m"
echo -e "\033[34m 蓝色字体 long \033[0m"
echo -e "\033[35m 洋红色字体 long \033[0m"
echo -e "\033[36m 蓝绿色字体 long \033[0m"
echo -e "\033[37m 白色字体 long \033[0m"

7. for循环语句

for循环语句和while循环语句类似,但for循环主要用于执行次数有限的循环,而不是用于守护进程及无限循环。


1.for循环语法结构:
for 变量名 in 变量取值列表
do
指令...
done

tips:在此结构中,“in 变量取值列表”可以省略,省略时相当于in "$@",也就是使用for i就相当于使用for i in "$@"

在这种for循环语句结构语法中,for关键字后面有一个变量名,变量名依次获取in关键字后面的变量取值列表内容(以空格隔开),每次取一个,然后进入循环执行循环内的指令,当执行到done时结束本次循环。之后,“变量名”再继续获取列表里的下一个变量值,继续执行循环体内的指令,当执行到done时结束返回,以此类推,直到取完列表里的最后一个值并进入循环执行到done结束为止。

第二种语法结构:
for((expr1;expr2;expr3))
do
指令...
done

范例1:计算1-100整数和

#!/bin/bash
declare -i SUM=0

for I in {1..100};do
	let SUM+=$I
done
echo $SUM

declare -i SUM2=0
for ((I=1;I<=100;I++));do
	let SUM2+=$I
done
echo $SUM2
范例2:竖向打印5、4、3、2、1这5个数字
#!/bin/bash
for I in `seq 5 -1 1`
do 
echo $I
done

8. while循环语句

循环语句命令常用于重复执行一条指令或一组指令,直到条件不满足为止,shell脚本语言的循环语句常见的有while、until、for、select循环语句。
while循环语句主要用来重复执行一组命令或语句,在企业实际应用中,常用于守护进程或持续运行的程序,除此以外,大多数循环都会用到for循环语句

1.while循环语句语法:

while <条件表达式>
do
指令...
done
while循环语句会对紧跟while命令后的条件表达式进行判断,如果该条件表达式成立,则执行while循环体中的命令或语句,每一次执行到done时,就会重新判断while条件表达式是否成立,直到条件表达式不成立时才会跳出while循环体。如果一开始条件表达式就不成立,那么程序就不会进入循环体。

while的特殊用法一,死循环:
while :;do
  
done

举例输入文件路径,进行判断:
#!/bin/bash
while :;do
	read -p "File path:" FILEPATH
	[ $FILEPATH == 'quit'] && break
	if [ -e $FILEPATH ];then
		echo "$FILEPATH exists"
	else
		echo "No $FILEPATH."
	fi
done


while的特殊用法二:
while read LINE; do

done < /PATH/TO/SOMEFILE

举例:判断/etc/passwd中哪个用户的shell为bash shell,如果是bash shell就显示该用户的用户名

#!/bin/bash
#
FILE=/etc/passwd

while read LINE;do
	[ `echo $LINE |awk -F: '{print $7}'` == '/bin/bash' ] && echo $LINE |awk -F: '{print $1}'
done < $FILE


2.until循环语句语法:
until <条件表达式>
do
指令...
done
until的用户和while类似,区别是until会在条件表达式不成立时,进入循环执行指令;条件表达式成立时,终止循环。

范例1:
1、判断一个指定的bash脚本是否有语法错误;如果有错误,则提醒用户键入Q或者q无视错误并退出,其它任何键可以通过vim打开这个指定的脚本;
2、如果用户通过vim打开编辑后保存退出时仍然有错误,则重复第1步中的内容;否则,就正常关闭退出。

./syntax.sh a.sh

until bash -n $1 &> /dev/null; do
	read -p "Syntax error, [Qq] to quit, others for editing: "  CHOICE
	case $CHOICE in
	q|Q)
	    echo "Something wrong, quiting."
	    exit 5
	    ;;
	*)
		vim + $1
		;;
	esac
done

echo "0K"

break: 提前退出循环
continue:提前结束本轮循环,而进入下一轮循环;

计算1-100的奇数和
#!/bin/bash

let SUM=0
let I=1
while [ $I -le 100 ];do
	if [ $[$I%2] -eq 1 ];then
		let SUM+=$I
	fi
		let I++
done
echo $SUM

continue举例:
#!/bin/bash
let SUM=0
let I=0
while [ $I -lt 100 ];do
	let I++
	if [ $[$I%2] -eq 0 ];then
		continue---当判断取余为0时,直接提前结束本轮循环体
	fi
	let SUM+=$I
done
echo $SUM

break举例:
#!/bin/bash
#
let SUM=0
for I in {1..1000};do
	let SUM+=$I
	if [ $SUM -gt 5000 ];then
		break---直接退出循环
	fi
done
echo $I
echo $SUM

企业生产范例:
写一个shell脚本解决类DDOS攻击的生产案例。请根据web日志或系统网络连接数,监控某个ip的并发连接数,若短时间内PV达到100,即调用防火墙命令封掉对应的ip,防火墙命令为:iptables -I INPUT -s IP地址 -j DROP

#!/bin/bash
file=$1
while true;do
awk '{print $1}' $1 |grep -v "^$"|sort |uniq -c > /tmp/tmp.log
exec </tmp/tmp.log
while read line
do
ip=`echo $line |awk '{print $2}'`
count=`echo $line |awk 'print $1'`
if [ $count -gt 500 ] && [ `iptables -L -n|grep "$ip"|wc -l` -lt 1 ]
then
iptables -I INPUT -s $ip -j DROP
echo "$line is droped" >> /tmp/droplist_$(date +%F).log
fi
done
sleep 3600
done

9. 函数

函数的功能:实现代码的重用

9.1 shell函数的常见语法

标准写法:
function 函数名 () {
指令...
return n
}
简化写法1:
fucntion 函数名 {
指令...
return n
}
简化写法2:
函数名 () {
指令...
return n
}
tips:在shell函数语法中,function表示声明一个函数,这部分可以省略不写。

9.2 shell函数的执行

shell的函数分为最基本的函数和可以传参的函数两种,其执行的方式分别如下:

  • ①执行不带参数的函数时,直接输入函数名即可(注意不带小括号)。
    格式如下:函数名
    说明:执行函数时,函数名前的function和函数后的小括号都不用带;
    函数的定义必须要在执行的程序前面定义或加载;
    return命令和exit命令类似,return的作用是退出函数,exit是退出脚本文件
    如果将函数放在独立的文件中,被脚本加载时,需要使用source或"."来加载
    函数内,一般使用local定义的局部变量,这些变量离开函数后就会消失;

  • ②带参数的函数执行方法,
    格式如下:函数名 参数1 参数2
    说明:shell的位置参数($1、 2... 2... 2...#、 ∗ 、 *、 @、$?)都可以作为函数的参数来使用;
    此时父脚本的参数临时地被函数参数所掩盖或隐藏;
    $0比较特殊,它仍是父脚本的名称
    当函数执行完成时,原来的命令行脚本的参数即可恢复;
    函数的参数变量是在函数体里面定义的;

举例:使用函数多次显示一个菜单

#!/bin/bash
#
function SHOWMENU {
cat << EOF
d|D) show disk usages
m|M) show memory usages
s|S) show swap usages
q|Q) quit
EOF
}
SHOWMENU
SHOWMENU
SHOWMENU

范例1:将函数的传参转换成脚本文件命令行传参,判断任意指定的URL是否存在异常.
1)实现脚本传参,检查web URL是否正常。
#!/bin/bash
#判断传参数量是否为1
if [ $# -ne 1 ];then
echo "Usage:`basename $0` url."
exit 1
fi
#利用wget进行访问
wget --spider -q -o /dev/null --tries=1 -T 5 $1 #T为超时时间,$1为脚本参数
if [ $? -eq 0 ];then
echo "$1 is yes."
else
echo "$1 is no."
fi
2)将上述检测的功能写成函数,并将函数传参转换成脚本命令行传参,判断任意指定的URL是否存在异常。
#!/bin/bash
function usage() {
echo "Usage:`basename $0` url."
exit 1
}
function check_url() {
wget --spider -q -o /dev/null --tries=1 -T 5 $1
if [ $? -eq 0 ];then
echo "$1 is yes."
else
echo "$1 is no."
fi
}
function main() {
if [ $# -ne 1 ];then
useage
fi
check_url $1
}
main $* --这里的$*就是把命令行接收的所有参数作为函数参数穿给函数内部,是一种常用手法

10. 数组

1.shell数组的定义:
方法1:用小括号将变量值括起来赋值给数组变量,每个变量之间要用空格进行分隔。
语法如下:
array=(value1 value2 value3...)

[root@localhost ~]# array=(1 2 3)
[root@localhost ~]# echo ${array[*]}
1 2 3

方法2:动态定义数组变量,使用命令的输出结果作为数组的内容。
语法为:
array=($(命令))	或  array=(`命令`)
示例如下:
[root@localhost ~]# mkdir /array/ -p
[root@localhost ~]# touch /array/{1..3}.txt
[root@localhost ~]# ll /array/
total 0
-rw-r--r-- 1 root root 0 Aug 23 21:45 1.txt
-rw-r--r-- 1 root root 0 Aug 23 21:45 2.txt
-rw-r--r-- 1 root root 0 Aug 23 21:45 3.txt
[root@localhost ~]# array=($(ls /array/))
[root@localhost ~]# echo ${array[*]}
1.txt 2.txt 3.txt

2.shell数组的打印及输出
①打印数组元素
[root@localhost ~]# array=(1 2 3)
[root@localhost ~]# echo ${array[0]}
1
[root@localhost ~]# echo ${array[1]}
2
[root@localhost ~]# echo ${array[2]}
3
②打印数组元素个数
[root@localhost ~]# echo ${array[*]}	--使用*或@可以得到整个数组的内容
1 2 3
[root@localhost ~]# echo ${#array[*]}	-使用${#数组名[*]}可以得到数组的长度
3
[root@localhost ~]# echo ${array[@]}
1 2 3
[root@localhost ~]# echo ${#array[@]}
3
③数组的删除
因为数组的本质还是变量,因此可以通过unset 数组[下标] 清除相应的数组元素,如果不带下标,则表示清除整个数组的所有数据。

④数组内容的截取与替换
[root@localhost ~]# array=(1 2 3 4 5)
[root@localhost ~]# echo ${array[@]:1:3}	-截取1号到3号数组元素
2 3 4
[root@localhost ~]# echo ${array[@]/1/a}	-把数组中的1替换成a
a 2 3 4 5
[root@localhost ~]# echo ${array[@]}
1 2 3 4 5

tips:调用方法为${数组名[@或*]/查找字符/替换字符},该操作不会改变原数组的内容。

范例1:使用循环批量输出数组元素
#!/bin/bash
array=(1 2 3 4 5)
for((i=0;i<${#array[@]};i++))
do
echo ${array[i]}
done

范例2:利用bash for循环打印下面这句话中不大于6的单词
I am oldboy teacher welcome to oldboy training class
#!/bin/bash
array=(I am oldboy teacher welcom to oldboy training class)
for((i<0;i<${#array[@]};i++))
do
length=`echo ${array[i]} |wc -l`
if [ $length -lt 6 ];then
echo ${array[i]}
fi
done

11. 文件包含

可以使用source和.关键字,如:

source ./function.sh

. ./function.sh

在bash里,source和.是等效的,他们都是读入function.sh的内容并执行其内容(类似PHP里的include),为了更好的可移植性,推荐使用第二种写法。

包含一个文件和执行一个文件一样,也要写这个文件的路径,不能光写文件名,比如上述例子中:

. ./function.sh

不可以写作:

. function.sh

如果function.sh是用户传入的参数,如何获得它的绝对路径呢?方法是:

real_path=`readlink -f $1`#$1是用户输入的参数,如function.sh

. $real_path
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值