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

Shell编程入门总结(一)

2016-04-28 21:55 621 查看
本文的主要内容:

1、编写Shell脚本的一般步骤

2、在Shell脚本中输出文本

3、Shell脚本中的变量

4、Shell脚本中的函数

5、流程控制:if 分支结构

6、Shell中读取键盘输入

一、编写Shell 脚本

一般步骤:1.编写一个脚本 2.使脚本文件可执行 3.把脚本放置到 shell 能够找到的地方

例如:

1.编写hello_world脚本

#!/bin/bash
# This is our first script.
echo 'Hello World!'


2.赋予可执行权限

chmod 700 hello_world


3.执行脚本

./hello_world


4.若想让系统中的每个用户都可以使用, 那么可将脚本放到 /usr/local/bin,系统管理员使用的脚本经常放到 /usr/local/sbin 目录下。

二、Shell中输出文本

使用echo方式

例如:
echo "a string"


使用"here document"方式(可以随意的嵌入引号)

格式如下:

command << token
text
token

这里的 command 是一个可以接受标准输入的命令名,token 是一个用来指示嵌入文本结束的字符串

把操作符"<<"改为 "<<-",shell 会忽略开头的 tab 字符,可使用缩进提高可读性

例如:

cat << _EOF_
a string
_EOF_




cat <<- _EOF_
a string
_EOF_


例子:使用 一个 here document 将一系列的命令传递到 ftp 程序中以从一个远端 FTP 服务器中得到一个文件

#!/bin/bash
# Script to retrieve a file via FTP
FTP_SERVER=***
FTP_PATH=***
REMOTE_FILE=***
ftp -n << _EOF_
open $FTP_SERVER
user anonymous me@linuxbox
cd $FTP_PATH
hash
get $REMOTE_FILE
bye
_EOF_
ls -l $REMOTE_FILE


三、Shell脚本中的变量

创建变量或给变量赋值

variable=value(注:等号左右不能有空格)

可以在同一行中对多个变量赋值

a=5 b="a string"

使用变量

$variable 或 ${variable}

例如

b="a string"
c="a string and $b"
mv $filename ${filename}1


四、Shell中的函数

函数语法形式(其中name为函数名,commands为一系列包含在函数中的命令,函数中须至少包含一条命令,return为可选)

function name {

commands

return

}



name () {

commands

return

}

*例如

#!/bin/bash
function_1 () {
echo "Function_1 executed."
return
}
cat << _EOF_
$(function_1)
_EOF_


局部变量

*例如

funct_1 () {
local foo  #funct_1中的局部变量
foo=1
echo "funct_1: foo = $foo"
}


五、流程控制:if 分支结构

if 语句语法如下

if commands; then
commands
[elif commands; then
commands...]
[else
commands]
fi

*例如:

x=5
if [ $x = 5 ]; then
echo "x equals 5."
else
echo "x does not equal 5."
fi


退出状态

当命令执行完毕后会给系统发送一个值,叫做退出状态。Shell 提供了一个参数$?可用来检查退出状态

例如:(状态0为命令执行成功)

$ ls -d /usr/bin
/usr/bin
$ echo $?
0

测试

*经常与 if 一块使用的命令是 test。test 命令执行各种各样的检查与比较,它有两种等价模式:

test expression

[ expression ]

*其中expression 为一个表达式,其执行结果是 true 或者是 false。当表达式为真时,这个 test 命令返回一个0退出状态,当表达式为假时,test 命令退出状态为1

测试表达式

*文件表达式

file1 -ef file2:file1 和 file2 拥有相同的索引号(通过硬链接两个文件名指向相同的文件)
file1 -nt file2:file1新于 file2
file1 -ot file2:file1早于 file2
-b file:file 存在并且是一个块(设备)文件
-c file:file 存在并且是一个字符(设备)文件
-d file:file 存在并且是一个目录
-e file:file 存在
-f file:file 存在并且是一个普通文件
-g file:file 存在并且设置了组 ID
-G file:file 存在并且由有效组 ID 拥有
-k file:file 存在并且设置了它的“sticky bit”
-L file:file 存在并且是一个符号链接
-O file:file 存在并且由有效用户 ID 拥有
-p file:file 存在并且是一个命名管道
-r file:file 存在并且可读(有效用户有可读权限)
-s file:file 存在且其长度大于零
-S file:file 存在且是一个网络 socket
-t fd:fd 是一个定向到终端/从终端定向的文件描述符 。 这可以被用来决定是否重定向了标准输入/输出错误
-u file:file 存在并且设置了 setuid 位
-w file:file 存在并且可写(有效用户拥有可写权限)
-x file:file 存在并且可执行(有效用户有执行/搜索权限)

*文件表达式例子(其中在表达式中参数$FILE两边的引号并不是必需的,但这可防范空参数)

test_file () {
# test-file: Evaluate the status of a file
FILE=~/.bashrc
if [ -e "$FILE" ]; then
if [ -f "$FILE" ]; then
echo "$FILE is a regular file."
fi
if [ -d "$FILE" ]; then
echo "$FILE is a directory."
fi
if [ -r "$FILE" ]; then
echo "$FILE is readable."
fi
if [ -w "$FILE" ]; then
echo "$FILE is writable."
fi
if [ -x "$FILE" ]; then
echo "$FILE is executable/searchable."
fi
else
echo "$FILE does not exist"
return 1
fi
}


*字符串表达式

string:string 不为 null
-n string:字符串 string 的长度大于零
-z string:字符串 string 的长度为零
string1 = string2或string1 == string2:string1 和 string2 相同. 单或双等号都可以,不过双等号更受欢迎
string1 != string2:string1 和 string2 不相同
string1 > string2:sting1 排列在 string2 之后
string1 < string2:string1 排列在 string2 之前

注:> 和 <表达式操作符必须用引号引起来或者是用反斜杠转义,否则会被 shell 解释为重定向操作符,造成潜在地破坏结果

*字符串表达式例子:

#!/bin/bash
# test-string: evaluate the value of a string
ANSWER=maybe
if [ -z "$ANSWER" ]; then
echo "There is no answer." >&2
exit 1
fi
if [ "$ANSWER" = "yes" ]; then
echo "The answer is YES."
elif [ "$ANSWER" = "no" ]; then
echo "The answer is NO."
elif [ "$ANSWER" = "maybe" ]; then
echo "The answer is MAYBE."
else
echo "The answer is UNKNOWN."
fi


*整型表达式

integer1 -eq integer2:integer1 等于 integer2
integer1 -ne integer2:integer1 不等于 integer2
integer1 -le integer2:integer1 小于或等于 integer2
integer1 -lt integer2:integer1 小于 integer2
integer1 -ge integer2:integer1 大于或等于 integer2
integer1 -gt integer2:integer1 大于 integer2

*整型表达式例子:

#!/bin/bash
# test-integer: evaluate the value of an integer.
INT=-5
if [ -z "$INT" ]; then
echo "INT is empty." >&2
exit 1
fi
if [ $INT -eq 0 ]; then
echo "INT is zero."
else
if [ $INT -lt 0 ]; then
echo "INT is negative."
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd."
fi
fi


更现代的测试版本

*目前的 bash 版本包含一个复合命令:[[ expression ]],与test相比增加了一个重要的新的字符串表达式:string1 =~ regex,若string1匹配扩展的正则表达式 regex则返回真

例子:

#!/bin/bash
# test-integer2: evaluate the value of an integer.
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [ $INT -eq 0 ]; then
echo "INT is zero."
else
if [ $INT -lt 0 ]; then
echo "INT is negative."
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd."
fi
fi
else
echo "INT is not an integer." >&2
exit 1
fi


*为整数设计的复合命令:(( ))

例子:

#!/bin/bash
# test-integer2a: evaluate the value of an integer.
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if ((INT == 0)); then
echo "INT is zero."
else
if ((INT < 0)); then
echo "INT is negative."
else
echo "INT is positive."
fi
if (( ((INT % 2)) == 0)); then
echo "INT is even."
else
echo "INT is odd."
fi
fi
else
echo "INT is not an integer." >&2
exit 1
fi


通过使用逻辑操作符来结合表达式

操作符测 试[[ ]] 和 (( ))
AND-a&&
OR-o||
NOT!!
控制操作符:分支的另一种方法

*bash 支持两种可以执行分支任务的控制操作符。这个 &&(AND)和||(OR)操作符作用如同复合命令[[ ]]中的逻辑操作符

*语法:command1 && command2 和 command1 || command2

*对于 && 操作符,只有当command1 执行成功后,才会执行 command2。对于 || 操作符,只有当command1 执行失败后, 才会执行command2

*例如:

$ mkdir temp && cd temp :在成功创建目录temp后跳转到temp
$ [ -d temp ] || mkdir temp :若目录 temp 不存在则创建这个目录
[ -d temp ] || exit 1 : 若目录temp不存在则返回退出状态1

六、读取键盘输入(交互)

read - 从标准输入读取单行数据

*语法形式:read [-options] [variable...]

*读取一个整数:

echo -n "Please enter an integer -> "
read var
echo "var = '$var'"


*给多个变量赋值:

echo -n "Enter one or more values > "
read var1 var2
echo "var1 = '$var1'"
echo "var2 = '$var2'"


*若没有提供变量名,shell 变量 REPLY 会包含数据行

echo -n "Enter one or more values > "
read
echo "REPLY = '$REPLY'"


*read选项

-a array:把输入赋值到数组 array 中,从索引号零开始
-d delimiter:用字符串 delimiter 中的第一个字符指示输入结束,而不是一个换行符
-e:使用 Readline 来处理输入。这使得与命令行相同的方式编辑输入
-n num:读取 num 个输入字符,而不是整行
-p prompt:为输入显示提示信息,使用字符串 prompt

-r:Raw mode. 不把反斜杠字符解释为转义字符
-s:Silent mode. 不会在屏幕上显示输入的字符。当输入密码和其它确认信息的时候,这会很有帮助
-t seconds:超时. 几秒钟后终止输入。read 会返回一个非零退出状态,若输入超时
-u fd:使用文件描述符 fd 中的输入,而不是标准输入

*read选项例子:

#!/bin/bash
if read -t 10 -sp "Enter secret pass phrase > " secret_pass; then
echo -e "\nSecret pass phrase = '$secret_pass'"
else
echo -e "\nInput timed out" >&2
exit 1
fi
*此脚本提示用户输入一个密码,若在10秒内没有完成输入,则脚本会退出并返回一个错误。因包含了一个 -s 选项,所以输入的密码不会出现在屏幕上。

校正输入

*校正各种输入的示例程序:

#!/bin/bash
invalid_input () {
echo "Invalid input '$REPLY'" >&2
exit 1
}
read -p "Enter a single item > "
# input is empty (invalid)
[[ -z $REPLY ]] && invalid_input
# input is multiple items (invalid)
(( $(echo $REPLY | wc -w) > 1 )) && invalid_input
# is input a valid filename?
if [[ $REPLY =~ ^[-[:alnum:]\._]+$ ]]; then
echo "'$REPLY' is a valid filename."
if [[ -e $REPLY ]]; then
echo "And file '$REPLY' exists."
else
echo "However, file '$REPLY' does not exist."
fi
# is input a floating point number?
if [[ $REPLY =~ ^-?[[:digit:]]*\.[[:digit:]]+$ ]]; then
echo "'$REPLY' is a floating point number."
else
echo "'$REPLY' is not a floating point number."
fi
# is input an integer?
if [[ $REPLY =~ ^-?[[:digit:]]+$ ]]; then
echo "'$REPLY' is an integer."
else
echo "'$REPLY' is not an integer."
fi
else
echo "The string '$REPLY' is not a valid filename."
fi


菜单,一种常见的交互类型称为菜单驱动

*菜单驱动例子

#!/bin/bash
# read-menu: a menu driven system information program
clear
echo "
Please Select:

1. Display System Information
2. Display Disk Space
3. Display Home Space Utilization
0. Quit
"
read -p "Enter selection [0-3] > "

if [[ $REPLY =~ ^[0-3]$ ]]; then
if [[ $REPLY == 0 ]]; then
echo "Program terminated."
exit
fi
if [[ $REPLY == 1 ]]; then
echo "Hostname: $HOSTNAME"
uptime
exit
fi
if [[ $REPLY == 2 ]]; then
df -h
exit
fi
if [[ $REPLY == 3 ]]; then
if [[ $(id -u) -eq 0 ]]; then
echo "Home Space Utilization (All Users)"
du -sh /home/*
else
echo "Home Space Utilization ($USER)"
du -sh $HOME
fi
exit
fi
else
echo "Invalid entry." >&2
exit 1
fi
*从逻辑上讲,这个脚本被分为两部分。第一部分显示菜单和用户输入。第二部分确认用户反馈,并执行 选择的行动

参考:《The Linux Command Line》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: