您的位置:首页 > 运维架构 > Shell

Shell学习笔记

2016-10-05 20:42 169 查看
这是自己学习Shell的一点笔记,主要参考的是http://www.runoob.com/linux/linux-shell.html

Shell介绍

Shell既是一种命令语言,又是一种程序设计语言

作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

Shell两种执行命令的方式

交互式(Interactive):解释执行用户的命令,用户输入一条命令,Shell就解释执行一条。

批处理(Batch):用户事先写一个Shell脚本(Script),其中有很多条命令,让
Shell
一次把这些命令执行完,而不必一条一条地敲命令。

常见的Shell

bash:Linux标准的shell

其他sh,csh,ksh

第一个shell

#!/bin/bash

echo "Hello World!"


#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。echo命令用于向窗口输出文本。

shell的执行方式有两种:直接运行或者用shell执行。

Shell 变量:Shell 变量的定义、删除变量、只读变量、变量类型

定义变量

定义时直接赋值,使用时用 “$”符号,最好使用花括号。

#!/bin/bash

myUrl="blog.csdn.net/charles1e"
myName="yanke"
echo ${myUrl}
echo ${myName}
myName="Yan Ke"
echo ${myName}


只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变

#!/bin/bash

myUrl="www.blog.net/charles1e"
readonly myUrl
myUrl="www.blog.net/charles"


运行:

./ReadOnlyVariable.sh: line 5: myUrl: readonly variable


删除变量

使用 unset 命令可以删除变量。变量被删除后不能再次使用;unset 命令不能删除只读变量。

#!/bin/bash

myName="Yan Ke"
unset myName
echo ${myName}


没有任何输出。

变量类型

局部变量

环境变量

shell变量

Shell 特殊变量



Shell替换



Shell 运算符:Shell 算数运算符、关系运算符、布尔运算符、字符串运算符等

算术运算符

表达式和运算符要有空格

完整的表达式要被“包围

条件表达式要放在方括号之间,并且有空格

a=10
b=20
val=`expr $a + $b`
echo "a+b: ${val}"

val=`expr $a - $b`
echo "a-b: ${val}"

val=`expr $a \* $b`
echo "a*b: ${val}"

val=`expr $b / $a`
echo "b/a: ${val}"

val=`expr $b % $a`
echo "b%a: $val"

if [ $a == $b ]
then
echo "a is equal to b"
fi

if [ $a != $b ]
then
echo "a is not equal to b"
fi




关系运算符

#!/bin/bash

a=10
b=20

if [ $a -eq $b ]
then
echo "$a -eq $b : a is equal to b"
fi

if [ $a -ne $b ]
then
echo "$a -ne $b : a is not equal to b"
fi

if [ $a -gt $b ]
then
echo "$a -gt $b : a is greater than b"
else
echo "$a -gt $b : a is not greater than b"
fi

if [ $a -lt $b ]
then
echo "$a -lt $b : a is lese than b"
else
echo "$a -lt $b : a is not less than b"
fi

if [ $a -ge $b ]
then
echo "$a -ge $b : a is greater or equal to b"
else
echo "$a -ge $b : a is not greater or equal to b"
fi




布尔运算符

!
: 非

-o
: 或

-a
: 与

字符串运算符

=
检测两个字符串是否相等,相等返回 true。

!=
检测两个字符串是否相等,不相等返回 true。

-z
检测字符串长度是否为0,为0返回 true。

-n
检测字符串长度是否为0,不为0返回 true。

str
检测字符串是否为空,不为空返回 true。

文件测试

#!/bin/bash

file="./helloworld.sh"

if [ -r $file ]
then
echo "File has read access"
else
echo "File does not have read access"
fi

if [ -w $file ]
then
echo "File has write access"
else
echo "File does not have write permission"
fi

if [ -x $file ]
then
echo "File has execute permission"
else
echo "File has no execute permission"
fi

if [ -f $file ]
then
echo "File is an ordinary file"
else
echo "This is a special file"
fi

if [ -d $file ]
then
echo "File is a directory"
else
echo "This ia not a directory"
fi

if [ -s $file ]
then
echo "File size is zero"
else
echo "File size is not zero"
fi

if [ -e $file ]
then
echo "File exits"
else
echo "File does not exit"
fi


File has read access
File has write access
File has execute permission
File is an ordinary file
This ia not a directory
File size is zero
File exits


-b file
检测文件是否是块设备文件,如果是,则返回 true。

-c file
检测文件是否是字符设备文件,如果是,则返回 true。

-d file
检测文件是否是目录,如果是,则返回 true。

-f file
检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。

-g file
检测文件是否设置了 SGID 位,如果是,则返回 true。

-k file
检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。

-p file
检测文件是否是具名管道,如果是,则返回 true。

-u file
检测文件是否设置了 SUID 位,如果是,则返回 true。

-r file
检测文件是否可读,如果是,则返回 true。

-w file
检测文件是否可写,如果是,则返回 true。

-x file
检测文件是否可执行,如果是,则返回 true。

-s file
检测文件是否为空(文件大小是否大于0),不为空返回 true。

-e file
检测文件(包括目录)是否存在,如果是,则返回 true。

Shell注释

#
开头的行就是注释,会被解释器忽略。

sh 里没有多行注释

Sheel字符串

只有字符串和数字

字符串可以用单引号也可以用双引号

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

双引号的优点: 双引号里可以有变量 双引号里可以出现转义字符

字符串拼接

#!/bin/bash

name="yanke"
greeting="hello, "${name}"!"
greeting1="hello, ${name}!"
echo ${greeting} ${greeting1}


字符串长度

$ string="abcd"
$ echo ${#string}
4


字符串截取

$ string="Talk is cheap,show me the code!"
$ echo ${string:1:4}
alk


Shell数组

bash支持一维数组,没有限定数组的大小,数组下标从0开始

定义数组

array_name=(value0 value1 value2 value3)


可以单独定义数组的各个分量

可以不使用连续的下标,而且下标的范围没有限制。

读取数组

${array_name[index]}


#!/bin/bash

Name[0]='Zara'
Name[1]='Qadir'
Name[2]='Mahnaz'
Name[3]='Ayan'
#访问数组中的元素
echo "first index: ${Name[0]}"
echo "Second inde;inde;x: ${Name[1]}"
#输出所有的元素
echo "First Method:${Name[*]}"
echo "Second Method:${Name[@]}"
#获取数组的长度
length=${#Name[*]}
#或者是
#length=${#Name[@]}
#获取单个元素的长度
lengthn=${#Name[2]}
echo "The length of Name:${length}"
echo "The length of Name[2]:${lengthn}"


first index: Zara
Second inde;inde;x: Qadir
First Method:Zara Qadir Mahnaz Ayan
Second Method:Zara Qadir Mahnaz Ayan
The length of Name:4
The length of Name[2]:6


Shell echo命令

#!/bin/bash

#echo的使用方法如下:
#echo arg

#显示转义字符
echo "\"It is a test\""

#显示变量
name="OK"
echo "${name} It is a test"

#显示换行
echo -e "OK! \n"  #-e 开启转义
echo "It's a test"

#不换行
echo -e "OK!\c"
echo "It's a test"

#结果定向到文件
echo "It is a test" > myfile

#原样输出字符串
echo '$name\"'

#显示命令执行结果
echo `date`


"It is a test"
OK It is a test
OK!

It's a test
OK!It's a test
$name\"
Thu Sep 29 22:08:53 CST 2016


Shell printf命令

#!/bin/bash

#printf的格式一般为:
#printf format-string [arguments..]
#format-string为格式控制字符串
#arguments为参数列表

echo "Hello, Shell!"
printf "Hello Shell\n" #printf需要手动换行

##格式化输出
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

#format-string为双引号
printf "%d %s\n" 1 "abc"

#单引号与双引号一样
printf '%d %s\n' 1 "abc"

#没有引号也可以输出
printf %s abcdef

#格式指指定了一个参数,但是多出的参数仍然会按照这个格式输出
printf %s abc def
printf "%s\n" abc def
printf "%s %s %S \n" a b c d e f g h i j
#如果没有guments,那么%s用NULL替代,%d用 0 替代
printf "%s and %d\n"


转义字符:

\a
警告字符,通常为ASCII的BEL字符

\b
后退

\c
抑制(不显示)输出结果中任何结尾的换行字符(只在
%b
格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略

\f
换页(formfeed)

\n
换行

\r
回车(Carriage return)

\t
水平制表符

\v
垂直制表符

\\
一个字面上的反斜杠字符

\ddd
表示1到3位数八进制值的字符。仅在格式字符串中有效

\0ddd
表示1到3位的八进制值字符

Shell流程控制

#!/bin/bash

#for循环
for loop in 1 2 3 4 5
do
echo "The value is : $loop"
done

#while语句
i=1
while(( ${i}<=5 ))
do
echo $i
let "i++"
done

#while读取键盘输入
#echo "按 <CTRL-D> 退出"
#echo -n "输入你最喜欢的电影名:"
#while read FILM
#do
#    echo "是的!${FILM}是一部好电影"
#done

#until循环:一般很少用,用while就行了

#case多路选择
echo "输入1到4之间的数字"
echo -n "你输入的数字为:"
read aNum
case ${aNum} in
1) echo "你选择了1"
;;
2) echo "你选择了2"
;;
3) echo "你选择了3"
;;
4) echo "你选择了4"
;;
*) echo "你没有输入1到4之间的数"
;;
esac

#跳出循环
#break跳出所有循环
#continue跳出当前循环
while :
do
echo -n "输入1到5之间的数字:"
read num
case ${num} in
1|2|3|4|5) echo "你输入的数字为$num"
;;
*) echo "你输入的数字不是1到5之间,游戏结束!"
break
;;
esac
done

while :
do
echo -n "输入1到5之间的数字:"
read num
case ${num} in
1|2|3|4|5) echo "你输入的数字为$num"
;;
*) echo "你输入的数字不是1到5之间"
continue
echo "游戏结束"
;;
esac
done


Shell函数

$#
传递到脚本的参数个数

$*
以一个单字符串显示所有向脚本传递的参数

$$
脚本运行的当前进程ID号

$!
后台运行的最后一个进程的ID号

$@
$*
相同,但是使用时加引号,并在引号中返回每个参数。

$-
显示Shell使用的当前选项,与set命令功能相同。

$?
显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

#!/bin/bash

#函数定义
#1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
#2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)))

demoFuc()
{
echo "Hello world!"
}

echo "--------函数开始执行-----------"
demoFuc
echo "--------函数执行完毕-----------"

#带有返回值的函数:直接使用return
fucWithReturn()
{
echo "对输入的两个数字相加"
echo -n "请输入第一个数字:"
read num1
echo -n "请输入第二个数字:"
read num2
echo "输入的两个数字为${num1}和${num2}"
return $((${num1} + ${num2}))
}

fucWithReturn
echo "和为:$? ."

#带有参数的函数:$n的形式传递

funWithParam()
{
echo "第一个参数为:$1 ."
echo "第二个参数为:$2 ."
echo "第10个参数为:${10} ."
echo "参数的总数为:$# 个."
echo "输出所有的参数: $* ."
}

funWithParam 1 2 3 33 544 5 33 23 23 53 45 22 33


Shell输入/输出重定向

command > file
将输出重定向到 file。

command < file
将输入重定向到 file。

command >> file
将输出以追加的方式重定向到 file。

n > file
将文件描述符为 n 的文件重定向到 file。

n >> file
将文件描述符为 n 的文件以追加的方式重定向到 file。

n >& m
将输出文件 m 和 n 合并。

n <& m
将输入文件 m 和 n 合并。

<< tag
将开始标记 tag 和结束标记 tag 之间的内容作为输入。

Here Document

Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

它的基本的形式如下:

command << delimiter
document
delimiter


它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。

注意:

1. 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。

2. 开始的delimiter前后的空格会被忽略掉。

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到
/dev/null


$ command > /dev/null


/dev/null
是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是
/dev/null
文件非常有用,将命令的输出重定向到它,会起到”禁止输出”的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

$ command > /dev/null 2>&1


Shell文件包含

和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。

Shell 文件包含的语法格式如下:

. filename   # 注意点号(.)和文件名中间有一空格




source filename


创建两个 shell 脚本文件。

test1.sh 代码如下:

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

url="http://www.runoob.com"


test2.sh 代码如下:

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

#使用 . 号来引用test1.sh 文件
. ./test1.sh

# 或者使用以下包含文件代码
# source ./test1.sh

echo "菜鸟教程官网地址:$url"


接下来,我们为 test2.sh 添加可执行权限并执行:

$ chmod +x test2.sh


$ ./test2.sh


菜鸟教程官网地址:http://www.runoob.com


注:被包含的文件 test1.sh 不需要可执行权限。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shell