小杨同志

导航

 

shell编程学习总结-3

标签(空格分隔): 运维


编写和调试脚本

建立并且运行一个脚本

script.sh

#!/bin/bash

echo "the script starts now."
echo "Hi, $USER!"
echo

echo "I will now fetch you a list of connected users:"
echo 
w
echo

echo "I'm setting two variables now."
export COLOUR="red"
COLOUR="black"
VALUE="9"
echo "this is stinrg : $COLOUR"
echo "and this is a number: $VALUE"

在终端中执行这个脚本的,父进程会创建一个子进程,在子进程中执行这个脚本的内容。当子进程退出时候,控制权再次交给父进程,所以在子进程中创建的变量都会失效。包括export是变量,或者export改变的原有的变量的值,都会失效。

如果想用一个脚本调用另外一个脚本,并且需要另外一个脚本中的变量值,就需要source ./script.sh,这个意思是不创建进程,而是在当前脚本中执行,和sh中的'.'的意思是一样的,而且被调用的脚本也不需要有可执行权限。

脚本基础

#!/bin/bash决定要启用的shell
脚本最好要在首部写上此脚本的作用,如果在其他行的关键部位也有注释,就更好了

调试脚本

调试整个脚本
sh -x ./script.sh 

调试部分脚本
set -x
code..........
set +x

Bash环境

shell初始化文件

/etc/profile,/etc/inputrc,/etc/profile.d
这些配置文件应用到了所有用户。
/etc/profile,为每个用户设置环境信息,当用户第一次登陆时候运行

~/.bash_profile
用户其实需要增加针对自己的配置,或者更改默认设置。这时候就是这个文件了。这个文件一般也会执行 ~/.bashrc,~/.bash_login

~/.bash_login
这个文件包含了只有你在登陆系统的时候才执行的特殊设置,本机的ubuntu系统没有这个文件,一般情况下,在没有~/.bash_profile的时候才会找这个文件,如果同时存在这两个文件,那一般情况下,在~/.bash_profile中,也会执行了~/.bash_login

~/.profile
在没有~/.bash_profile, ~/.bash_login~的情况下,才会读取这个文件

~/.bashrc
在大多数情况下,是使用非登陆shell的,比如你的桌面linux,打开终端,从来没有让亲输入过用户名密码吧;无需认证;同时他也会读取登陆时的配置文件,所以无需重复添加。一般系统中不存在/etc/bashrc。这个文件中用户就可以自定义一些想立即生效的变量或者别名。利用xshell远程的ssh登陆时,会执行~/.bash_profile,也会执行~/.bashrc,如果复制一个xshell,仅会执行~/.bashrc

如何生效
重新连接系统或者source file这个配置文件。多数 shell 脚本在一个私有环境中执行:除非变量是父脚本 export 出来的,不然他们不会被子进程继承下来。

变量

变量的类型

全局变量
全局变量或者环境变量存在于所有的shell当中,printenv或env可以输出他们
本地变量
set可以显示所有变量的列表,包括环境变量和函数

建立变量

一般的变量只存在于当前shell,子shell不会知晓,

$full_name="perkyoung"
$bash
$echo $full_name

   //该值为空,因为那个变量是本地变量

想让子shell知道,就需要导出该变量,export full_name,导出的变量就像环境变量一样,对子shell可见,但是子shell对该导出变量做的更改,不会影响父shell本身

$full_name="perkyoung"
$export full_name
$bash
$echo $full_name
perkyoung
$export full_name="liguoli"
$exit
$echo $full_name
perkyoung

正则表达式

流编辑器SED

字符匹配

sed '/errors/p' example #匹配包含errors的行并输出,但是会输出两次
sed -n '/errors/p' example #这个只输出了一次
sed '/errors/d' example #删除包含errors的行

行匹配

sed '2,4d' example #删除2-4行
sed '3,$d' example #3-最后一行
sed '/a text/,/This/p' example #从``a text``到``This``的行

查找替换

sed 's/erors/errors/g' example
sed 's/^/>/g' example   #行首插入>
sed 's/$/EOL/g' example #行尾插入EOL
sed 's/erors/errors/g' -e 's/last/final/g' example

流编辑器AWK

条件语句

数字比较

#!/bin/bash
if [ ! -f ./aaa ] ; then
    echo "./aaa is not exist."
fi

LINENUM=`wc -l ./aaa` 
echo $LINENUM   # result is : 3 ./aaa

if test "$LINENUM" == "3"   #字符串的比较,喜欢用test替代[]
then
    echo "line num is 3"
fi

if test "$LINENUM" -eq "3"  #因为LINENUM包括字母,所以-eq就会有语法错误,只能用==进行字符串的比较
then
    echo "....."
fi

LINENUM=$(wc -l ./aaa | cut -f1 -d" ")  #取一个命令行行的结果的另一种方法
echo $LINENUM   #3
if test "$LINENUM" -eq "3" ; then   #只要LINENUM是数字,那无论是否是引号,或者换成==,都正确
    echo "...."
fi

字符串比较

if test $(whoami) == 'perkyoung'
then
        echo "is perkyoung"
fi

正则表达式匹配

#!/bin/bash
gender="192.168"
if [[ "$gender" =~ [0-9]{3}\.[0-9]+  ]] #两个双括号匹配
then
        echo "yes"
fi


NAME="perkyong"
REG='.+y.+'
if [[ $NAME =~ $REG ]]
then
        echo "yes"
fi

获取命令的返回状态

if ! grep $USER /etc/passwd 1>/dev/null #获取grep的返回状态,目测应该不是返回值,因为如果匹配到,返回值是0,取非之后是1,但是却没有走到下面的分支
then
    echo "have NO the account"
fi


YEAR=`date +%Y` 

if test $[$YEAR % 4] -eq "0"    #在中括号种进行运算,如果是命令的话,可以用`或者小括号
then
        echo "run nian"
else
        echo "no run nian"
fi

if test $[$YEAR % 4] == "0"  && (test  $[$YEAR % 4] != "1"  || ..... ) #将test换成[]也行,
then
    echo "....."
fi

SPACE="anquan"
case $SPACE in
start)
        echo "anquan"
;;
end)
        echo "bu anquan"
;;
*)
        echo "default"
;;
esac

编写交互脚本

显示用户消息

echo -e "name\tage" #-e选项可以用来专业反斜杠
echo -n "input:"    #-n选项不输出换行符

捕获用户输入

read name

重定向和文件描述符

$exec 100>./result   #指定文件描述符给文件
$ls -l * >& 100      #文件内容输出到该文件

$cat ./test
hello world perkyoung

exec 7<&0
exec < ./test   #test内容是
read name1 name2 name2
echo $name2 # hello
echo $name2 # world
echo $name3 # perkyoung
exec 7<&-   $关闭文件描述符

函数

#!/bin/bash

echo $(uname)           #shell解释性语言,不会是别处后面的uname,输出系统自带的uname命令结果
num=1000

uname(){
        echo "test!"
        num=$[$num+1]
        return 100 
}

testvar()
{
        local num=10
        num=$[$num+1]
        echo $num
}

uname   #调用自身定义的uname函数
echo $? #获取返回值100
echo $num   #uanme函数改变的是全局的num值
testvar
echo $num   #testvar改变的是局部变量的num,对外界没有影响

posted on 2015-07-12 01:38  小杨同志  阅读(163)  评论(0)    收藏  举报