shell编程

简介:

shell脚本 ,就是一个可执行文件,后缀为.sh,文件中是多条要顺序执行的linux命令。

 

一, Bash基本功能

1,历史命令调用

保存在~/.bash_history,使用history命令察看

上下箭头调用以前历史命令

!n 重复执行第n条命令

!! 重复执行上一条命令

!字串 重复执行最后一条以该字串开头的命令

 

2,命令和文件补全

tab键

 

3,别名,定义在~/.bashrc

alias

 

4,环境变量

$PATH

 

5,标准输入输出和文件描述符

键盘,/dev/stdin, 0, 标准输入

显示器,/dev/sdtout, 1, 标准输出

显示器,/dev/sdterr, 2, 标准错误输出

 

6,输出重定向

标准输出重定向:命令 > 文件,命令 >> 文件

标准错误输出重定向:错误命令 2>文件,错误命令 2>>文件

将正确和错误输出重定向到一个文件:命令 > 文件 2>&1,命令 >> 文件 2>&1

将正确和错误输出重定向到一个文件:命令 &> 文件 ,命令 &>> 文件 

将正确和错误输出分别保存:命令>>文件1 2>>文件2

不保存任何输出,丢入黑洞:ls &>/dev/null

 

7,输入重定向

wc 选项 文件名,统计字符,行数

文件 > wc

 

8,多命令顺序执行

; 顺序执行

&& 前一条命令必须成功执行,后一条才能执行

|| 前一条命令执行失败,后一条才能执行

 

9,管道符

|,可通过管道符连接两条命令,将第一条的输出当作第二条的输入

注意,有的命令不支持管道符,如find。可使用xargs命令,如

find /tmp -name CVS | xargs -n20 rm -rf

 

10,前后台运行

可以通过在命令后,添加符号“;”和“&”来分别以前台和后台的方式来执行。

 

11,环境变量

/etc/profile

/etc/profile.d/*.sh

~/.bash_profile

~/.bashrc

/etc/bashrc

 

二,如何写和执行:

1,如何写

vi filename.sh

文件中的linux命令用;号隔开。

 

2,如何执行

1>直接法:bash filename.sh

2>可执行文件法:

文件开头用 #!/bin/bash 声明使用的linux命令库;

赋予执行权限:chmod a+x filename.sh;

./filename.sh或/tmp/filename.sh

 

3,如何调试

set -x

 

 

三,程序设计

1,注释:#

 

2,变量

1>声明:可通过declare指定,-指定类型,+取消类型,-i声明为整形,-x声明为环境变量,-p显示变量类型

2>删除:unset

3>声明并赋值:name=value

4>调用:$name或${name}

5>数据类型:默认都为字符串

6>环境变量:$PATH,$HOME,$PWD,$USER,$UID,$SHELL, 察看当前环境变量set

7>预定义变量:$?命令执行后返回的状态,$$当前进程的进程号

8>导出变量:export name

被导出的变量在当前shell脚本执行的任何程序都会继承这个变量。如添加新路径:export PATH="$PATH:/home/user/bin"

9>导入配置文件中的变量:source file 或 .file

 

3,运算符

1>整数运算:$(()), $[],let,expr

a=4;b=5;
c=$(($a+$b))
c=$[$a+$b]
let c=$a+$b
c=$(expr $a + $b)       #运算符两边要空格!,运算符有+,-,*,/,%,&&,||

2>浮点运算:bc

"4*0.56" | bc                    #运算符有:+加,-减,*乘,/除,^指数,%余数,a(x) 正弦,c(x) 余弦

在运算前,可设置参数,用;号隔开。如设置精度:"scale=2;3/8" | bc

 

4,字符串操作

1>长度:${#name}

2>相连:${name}${age}

3>引号:单引号',双引号",反引号`的区别

单引号中的字符会被解析为字符串;如:name='Jason'。

反引号中的字符会被解析为命令。

双引号中的$会被解析为变量,如:name="${firstName}.${lastName}";

双引号中的`会被解析为命令,如:name="`whoami`"。

4>字符串转数组

string="a c d"

arr=($string)

5>字符串截取

string="http://www.baidu.com/index.html"

截取左边:string=${string#*//} 得到 "www.baidu.com/index.html"

截取右边:string=${string%/*} 得到 "www.baidu.com"

 

5,数组

1>定义:array_var=(1 2 3 4 5);

2>使用:${array_var[0]}

3>长度:${#array_var[*]}

4>全部:${array_var[*]}

5>添加:array_var=(${array_var[*]} ${newItem})

6>遍历

for((i=0;i<${#array_var[*]};i++))
do
  echo ${array_var[i]};
done

for var in ${array_var[*]}
do
  echo $var;
done

 

6,控制语句

1>条件:if,else

if [ $name = 'admin' ]
then
  echo 'admin';
fi
if [ $name = 'admin' ]
then
  echo 'admin';
else
  echo 'user';
fi
if [ $name = 'admin' ]
then
  echo 'admin';
elif [ $name = 'dba' ]
  echo 'dba';
else
  echo 'user';
fi

test 或 [ ] 支持判断数值、字符和文件

(1)数值测试:

-eq:等于
-ne:不等于
-gt:大于
-ge:大于等于
-lt:小于
-le:小于等于
(2)字符串测试:
=:等于
!=:不相等
-z 字符串:字符串长度为零
-n 字符串:字符串长度不为零
(3)文件测试:
-e 文件名:文件存在
-r 文件名:文件存在且可读
-w 文件名:文件存在且可写
-x 文件名:文件存在且可执行
-s 文件名:文件存在且至少有一个字符
-d 文件名:文件存在且为目录
-f 文件名:文件存在且为普通文件
-c 文件名:文件存在且为字符型文件
-b 文件名:文件存在且为块文件
非(”!”)、且(“-a”)、或(“-o")。三个逻辑操作符用于将测试条件连接起来。

注意:[]内侧和符号两边都要空格!!!

 

2>条件:case

read -p "Please choose yes/no: " -t 30 choose
case $choose in
        "yes")
                echo "user's choose is yes!"
                ;;
        "no")
                echo "user's choose is no!"
                ;;
        *)
                echo "user's choose is error!"
                ;;
esac

3>循环:for,while,until

固定循环 for:

for i in 1 2 3 4 5 6 7 8
        do
                echo $i
        done
for((i=0;i<10;i++))
do
 echo $i;
done

条件循环 while:

i=0;
while(($i<10))
do
 echo $i;
 let i++;
done

条件循环 until:

i=0;
until(($i==10))
do
 echo $i;
 let i++;
done

跳出循环:break,continue

 

7,函数

1>定义

function fname(){
statement;
}

2>调用

fname arg1 arg2;

3>参数

$1,$2...

参数个数:$#

全部参数字符串:$*

全部参数数组:$@

4>导出函数:export -f fname

4>返回值

return 返回整数

echo 返回字符串(函数中的命令如grep会影响输出,需要重定向)

4>引用

. ./function


 

四,常用命令

1,输入

从控制台获取输入 read var

1>密码:read -s var

2>提示:read -p "Enter input:" var

3>限制字符数:read -n 2 var

4>限制时间数:read -t 5 var

5>指定定界符:read -d "," var

 

2,输出

输出到控制台 echo, printf

1> echo:会自动换行。echo -e "\e[1;31m abcd \e[0m"  会将abcd打印为颜色,-e 为支持转义字符

2> printf:格式化输出。

%[-][length]type是格式替换符

type有s,f,替换字符串和浮点数;

length表示显示位数;

默认右对齐,添加-则左对齐

如:printf "%-10s %-4.2f\n" Smith 90.222

 

3,字符操作

搜索行:grep

-v 取反

 

字符流操作:sed

sed [options] 'command' file(s)

options:-i 则修改源文件;-e则多命令操作

command: 由两部分组成:定位+操作

定位:通过指定行号,正则表达式匹配。

操作:添加a;插入i;删除d;行替换c;字符替换s ; 全文正则表达式替换:s/old/new/g , \(re\)保存匹配的字符,用数字1使用;

 

按列提取:cut

-f 提取第几列

-d 指定分隔符,默认分隔符是tab,不支持空格为分隔符

 

按行操作:awk

格式:awk '条件1{动作1} 条件2{动作2}...' 文件名

条件一般用关系表达式最为条件,可以没有条件;动作一般为格式化输出或流程控制语句,默认动作是输出。

指定分隔符:-F,如awk  -F ':'  '{print $1}' /etc/passwd。默认域分隔符是"空白键" 或 "[tab]键"。

常量:FILENAME,文件名;NR,总共解析到第几行;FNR,本文件解析到第几行;NF,本行有几列

awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd

printf:格式化输出

awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd

搜索动作:/string/

awk -F: '/root/{print $7}' /etc/passwd

编程

起始,结尾做些事

cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "above is name shell pairs"}'

变量

awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd

条件语句

ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}' 

循环语句和数组

awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd

 

排序操作:sort

sort [选项] 文件名

-f:忽略大小写

-n:按数值排序,默认按字符

-r:反向排序

-t:指定分隔符,默认是tab

-k n[,m]:按照指定的列排序,从第n个字段开始,m字段结束,默认到行尾

sort -n -t ":" -k 3,3 /etc/passwd  #按照UID排序

 

统计操作:wc

wc [选项] 文件名

-l:只统计行数

-w:只统计单词数

-m:只统计字符数 

 

4,日期时间

1>查看时间:date

 

2>格式查看:年,月,日,星期,时,分,秒

date +%Y %b %d %a %H %M %S

3>修改时间:date --date "Jan 20 2014"

4>UTC时间:date +%s

5>延时执行:sleep

 

5,字符串trim

 #trim string
 #arg1 = string
 function trim(){
   echo $1 | sed -e 's/\(^ *\)//' -e 's/\( *$\)//' -e 's/\r//'
 }

 

6,数组contains

 #array contains() method
 #arg1 = array, arg2 = item
 function contains(){
   array=($@)
   arrayLength=$(( $# - 1 ))
   for((k=0;k<${arrayLength};k++))
   do
     arrayItem=${array[$k]}
     if [ $arrayItem = $2 ]
     then
       echo "true"
       return 0
     fi
   done
   echo "false"
 }


7,判断命令是否成功

 [ $? -eq "0" ];
    then
      echo "true";
    else
      echo "false";
  fi



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值