shell(1):shell基础及函数,字符串,if,while,时间处理等应用

提供给新手的shell帮助:文档


注意事项:

1.赋值的时候等号两边不能有空格
2.写[[]]和(()) 一定要注意前后中间都有空格


Shell中各种用法


---------------------------------------------------

shell中算数运算

--------------------------------------------------

1.若不是在for中需要用(())扩起来

方式1:
for((i=1;i<=196;++i))
do
 echo $i
done

方式2:
sum=0;
((sum++));
echo $sum

方式3:
sum=1;
sum=$[$sum+2];
echo $sum

方式4:
sum=1;
num2=1;
sum=$[$sum+$num2];
echo $sum

方式5:
sum=1;
let "sum++"

 

各种方法比较:
    方法一:typeset C=$(expr ${A} + ${B});
    SHELL中的基本工具,优点:方便检测变量是否为数字;缺点:只能计算整数,且只能计算加减法,不能计算乘除法

    方法二:let "C=${A}+${B}"; 或 let "C=A+B"
    内嵌命令计算,优点:能计算乘除法及位运算等;缺点:只能计算整数

    方法三:typeset C=$((A+B))
    CShell风格的计算,优点:能计算乘除法及位运算等,简介,编写方便;缺点:不能计算小数

    方法四:typeset C=${echo ${A} ${B} | awk '{print $1+$2}')
    使用awk计算,优点:能计算小数,可以实现多种计算方式,计算灵活;缺点:表达式太复杂

    方法五:typeset C=${echo ${A} + ${B} | bc -q)
    使用awk计算,优点:能计算小数,计算方式比awk还多,计算灵活;缺点:表达式太复杂,小数点后面的位数必须使

用scale=N来设置,否则可能会将结果截断为整数


--------------------------------------------
shell中if语句
--------------------------------------------
注意使用[[]]和(())一定要注意是有空格的,也就是所有符号两边都有空格

1.文件表达式
if [ -f  file ]    如果文件存在
if [ -d ...   ]    如果目录存在
if [ -s file  ]    如果文件存在且非空
if [ -r file  ]    如果文件存在且可读
if [ -w file  ]    如果文件存在且可写
if [ -x file  ]    如果文件存在且可执行  

2.整数变量表达式
if [ int1 -eq int2 ]    如果int1等于int2  
if [ int1 -ne int2 ]    如果不等于   
if [ int1 -ge int2 ]    如果>=
if [ int1 -gt int2 ]    如果>
if [ int1 -le int2 ]    如果<=
if [ int1 -lt int2 ]    如果<
可以使用-eq这些也可以使用==这些
如1:
if (($p != 14327))&&(($p != 26193));then
  
 sudo kill -9 $p
  
fi
如2:
if (($1 == 147));then return 3; fi

3.字符串变量表达式
if  [ $a = $b ]                 如果string1等于string2 字符串允许使用赋值号做等号
if  [ $string1 !=  $string2 ]   如果string1不等于string2      
if  [ -n $string  ]             如果string 非空(非0),返回0(true) 
if  [ -z $string  ]             如果string 为空
if  [ $sting ]                  如果string 非空,返回0 (和-n类似)   
如:
 if [ "$NOTKILLPIDS" = "" ] 注:=两边必须有空格


各种方法比较:
    方法一: if [ ${A} -lt ${B} ]; then ...
    这是最基本的比较方法,使用lt(小于),gt(大于),le(小于等于),ge(大于等于),优点:还没发现;缺点:只能比较整

数,使用lt,gt等不直观

    方法二: if ((${A} < ${B})) then ...
    这是CShell风格比较,优点:不用使用lt,gt等难记的字符串;缺点:还是只能比较整数

    方法三: if (echo ${A} ${B} | awk '!($1>$2){exit 1}') then ...
    这是使用awk比较,优点:可以比较小数;缺点:表达式太复杂,难记

    方法四: if (echo ${A} - ${B} | bc -q | grep -q "^-"); then ...
    这是使用bc计算比较,优点:可以比较小数;缺点:表达式更复杂,难记

 

--------------------------------------------
shell中逻辑与或非
--------------------------------------------
4.逻辑符
逻辑非 !              条件表达式的相反
if [ ! 表达式 ]
if [ ! -d $num ]      如果不存在目录$num


逻辑与 –a            条件表达式的并列,也可以用&&
if [ 表达式1  –a  表达式2 ]


逻辑或 -o             条件表达式的或,也可以用||
if [ 表达式1  –o 表达式2 ]

如:
f [ $ANS="Yes" -o $ANS="yes" -o $ANS="y" -o $ANS="Y" ]


--------------------------------------------
shell中while语句
--------------------------------------------
方式1:
sum=5
while (( $sum <=5 ))
do
done

方式2:

sum=5
while [[ $sum !=5 ]]
do
done


如列举循环:
#!/bin/sh

echo "Please input arguements is $# "
echo "What you input : "
while [[ $* != "" ]]
do
 echo $1
 shift
done


--------------------------------------------
shell中函数
--------------------------------------------
方法1:
#!/bin/bash
function fun1 {
  read -p "enter a: " a
  echo -n "print 2a: "
  return $[ $a * 2 ]
}
#函数调用
fun1
#获取函数返回值
value=$?

方法2:
#!/bin/bash
function fun1 {
  read -p "enter a: " a
  echo -n "print 2a: "
  return $[ $a * 2 ]
}
#获取函数返回值,注意有两个飘号
value=`fun1`
echo $value

方法3:向函数传递数据变量
#!/bin/bash
a=(11 12 13 14 15)
echo ${a[*]}
function array(){
  echo parameters : "$@"
  local factorial=1
  for value in "$@"
  do
    factorial=$[ $factorial * $value ]
  done
  echo $factorial
}
array ${a[*]}


方法4:函数返回数组变量
#!/bin/bash
a=(11 12 13 14 15)
function array(){
  echo parameters : "$@"
  local newarray=(`echo "$@"`)
  local element="$#"
  local i
  for (( i = 0; i < $element; i++ ))
  {
    newarray[$i]=$[ ${newarray[$i]} * 2 ]   
  }
  echo  new value:${newarray[*]}
}
result=`array ${a[*]}`
echo ${result[*]}

 

--------------------------------------------
shell中字符串的使用
--------------------------------------------
1.取长度:
str="abcd"
expr length $str   # 4
echo ${#str}       # 4
expr "$str" : ".*" # 4

2.查找子串位置
str="abc"
expr index $str "a"  # 1
expr index $str "b"  # 2
expr index $str "x"  # 0
expr index $str ""   # 0

3.选取子串
str="abcdef"
expr substr "$str" 1 3  # 从第一个位置开始取3个字符, abc
expr substr "$str" 2 5  # 从第二个位置开始取5个字符, bcdef
expr substr "$str" 4 5  # 从第四个位置开始取5个字符, def
echo ${str:2}           # 从第二个位置开始提取字符串, bcdef
echo ${str:2:3}         # 从第二个位置开始提取3个字符, bcd
echo ${str:(-6):5}      # 从倒数第二个位置向左提取字符串, abcde
echo ${str:(-4):3}      # 从倒数第二个位置向左提取6个字符, cde

4.截取子串
str="abbc,def,ghi,abcjkl"
echo ${str#a*c}     # 输出,def,ghi,abcjkl  一个井号(#) 表示从左边截取掉最短的匹配 (这里把abbc字串去掉)
echo ${str##a*c}    # 输出jkl,             两个井号(##) 表示从左边截取掉最长的匹配 (这里把abbc,def,ghi,abc

字串去掉)
echo ${str#"a*c"}   # 输出abbc,def,ghi,abcjkl 因为str中没有"a*c"子串
echo ${str##"a*c"}  # 输出abbc,def,ghi,abcjkl 同理
echo ${str#*a*c*}   # 空
echo ${str##*a*c*}  # 空
echo ${str#d*f)     # 输出abbc,def,ghi,abcjkl,
echo ${str#*d*f}    # 输出,ghi,abcjkl
echo ${str%a*l}     # abbc,def,ghi  一个百分号(%)表示从右边截取最短的匹配
echo ${str%%b*l}    # a             两个百分号表示(%%)表示从右边截取最长的匹配
echo ${str%a*c}     # abbc,def,ghi,abcjkl
可以这样记忆, 井号(#)通常用于表示一个数字,它是放在前面的;百分号(%)卸载数字的后面; 或者这样记忆,在键

盘布局中,井号(#)总是位于百分号(%)的左边(即前面)


5.子串替换
str="apple, tree, apple tree"
echo ${str/apple/APPLE}   # 替换第一次出现的apple
echo ${str//apple/APPLE}  # 替换所有apple
echo ${str/#apple/APPLE}  # 如果字符串str以apple开头,则用APPLE替换它
echo ${str/%apple/APPLE}  # 如果字符串str以apple结尾,则用APPLE替换它

5.1替换一批文件中所有的string
for i in file_list
do
vi $i <<-!
:g/xxxx/s//XXXX/g
:wq
!
done


6.字符串比较
[[ "a.txt" == a* ]]        # 逻辑真 (pattern matching)
[[ "a.txt" =~ .*\.txt ]]   # 逻辑真 (regex matching)
[[ "abc" == "abc" ]]       # 逻辑真 (string comparision)
[[ "11" < "2" ]]           # 逻辑真 (string comparision), 按ascii值比较

7.字符串连接
s1="hello"
s2="world"
echo ${s1}${s2}   # 当然这样写 $s1$s2 也行,但最好加上大括号

9.字符串反转
方法一:
使用rev命令

方法二:
编写脚本实现
复制代码 代码如下:
#!/usr/bin/awk -f
{
revline = ""
for (i=1;i<=length;i++)
{
revline = substr(,i,1) revline
}
}
END{print revline}

10.匹配
grep
egrep
fgrep

11.得到某个字符串中字符的重复次数
echo $a |awk -F"x" '{print NF-1}'


--------------------------------------------
shell中日期的操作
--------------------------------------------
#!/bin/sh

#---------------------------------
#接收日期转换为秒数
function mydate(){
        date --date="$1" +%s
}

#---------------------------------
#将秒数转换成标准时间
function mytime()
{
 #时间相加然后转换成标准时间格式
 
sum=100000000
 
sumtime=`date -d "@"$sum"" "+%Y-%m-%d %H:%M:%S"`
echo $sumtime
}

#--------------------------------
#接收两个日期,比较相差秒数
function differdate(){

           #将接收到的日期转换为秒
        a=`date --date="$1" +%s` 
        b=`date --date="$2" +%s`
        echo $a
        echo $b

        #比较a,b的大小
        if [ $a -gt $b  ]
         then

        #计算a,b的差值
         c=`expr $a - $b`
        echo $c
        else
         c=`expr $b - $a`
        echo $c
        fi
}

#-------------------------------
#接收两个日期,计算相差多少天
function differDay(){
        a=`date --date="$1" +%s`
        b=`date --date="$2" +%s`

        if [ $a -gt $b  ]
           then
           c=`expr $a - $b`

            #计算天数,scale=2即保留2为小数(使用bc工具,保留小数)
           d=`expr "scale=0;$c / 3600 / 24"|bc`
           echo $d
        else
           c=`expr $b - $a`
           d=`expr "scale=0;$c / 3600 / 24"|bc`
           echo $d
        fi
}


#分别调用函数

#mydate $1
#differdate $1 $2
differDay $1 $2

#---------------------------
#日期转天数
function date2days {
    echo "$*" | awk '{
        z=int((14-$2)/12); y=$1+4800-z; m=$2+12*z-3;
        j=int((153*m+2)/5)+$3+y*365+int(y/4)-int(y/100)+int(y/400)-2472633;
        print j
    }'
}
date2days `echo "2010-08-18 18:59:19" | sed 's/-/ /g;s/:/ /g'`


#---------------------------
#天数转日期
function days2date {
    echo "$1" | awk '{
        a=$1+2472632; b=int((4*a+3)/146097); c=int((-b*146097)/4)+a;
        d=int((4*c+3)/1461); e=int((-1461*d)/4)+c; m=int((5*e+2)/153);
        dd=-int((153*m+2)/5)+e+1; mm=int(-m/10)*12+m+3; yy=b*100+d-4800+int(m/10);
        printf ("%4d-%02d-%02d\n",yy,mm,dd)
    }'
}
days2date 14839

#---------------------------
#日期转分钟
function date2minutes {
    echo "$*" | awk '{
        z=int((14-$2)/12); y=$1+4800-z; m=$2+12*z-3;
        j=int((153*m+2)/5)+$3+y*365+int(y/4)-int(y/100)+int(y/400)-2472633;
        j=j*1440+$4*60+$5
        print j
    }'
}
date2minutes `echo "2010-08-18 18:59:19" | sed 's/-/ /g;s/:/ /g'`

#---------------------------
#分钟转日期
function minutes2date {
    echo "$1" | awk '{
        i=$1; nn=i%60; i=int(i/60); hh=i%24; dd=int(i/24); i=int(i/24);
        a=i+2472632; b=int((4*a+3)/146097); c=int((-b*146097)/4)+a;
        d=int((4*c+3)/1461); e=int((-1461*d)/4)+c; m=int((5*e+2)/153);
        dd=-int((153*m+2)/5)+e+1; mm=int(-m/10)*12+m+3; yy=b*100+d-4800+int(m/10);
        printf ("%4d-%02d-%02d %02d:%02d\n",yy,mm,dd,hh,nn)
    }'
}
minutes2date 21369299

#---------------------------
#日期转秒数
function date2seconds {
    echo "$*" | awk '{
        z=int((14-$2)/12); y=$1+4800-z; m=$2+12*z-3;
        j=int((153*m+2)/5)+$3+y*365+int(y/4)-int(y/100)+int(y/400)-2472633;
        j=j*86400+$4*3600+$5*60+$6
        print j
    }'
}
date2seconds `echo "2010-08-18 18:59:19" | sed 's/-/ /g;s/:/ /g'`

#---------------------------
#秒数转日期
function seconds2date {
    echo "$1" | awk '{
        i=$1; ss=i%60; i=int(i/60); nn=i%60; i=int(i/60); hh=i%24; dd=int(i/24); i=int(i/24);
        a=i+2472632; b=int((4*a+3)/146097); c=int((-b*146097)/4)+a;
        d=int((4*c+3)/1461); e=int((-1461*d)/4)+c; m=int((5*e+2)/153);
        dd=-int((153*m+2)/5)+e+1; mm=int(-m/10)*12+m+3; yy=b*100+d-4800+int(m/10);
        printf ("%4d-%02d-%02d %02d:%02d:%02d\n",yy,mm,dd,hh,nn,ss)
    }'
}
seconds2date 1282157959

#---------------------------
#日期转毫秒
function date2milliseconds {
    echo "$*" | awk '{
        z=int((14-$2)/12); y=$1+4800-z; m=$2+12*z-3;
        j=int((153*m+2)/5)+$3+y*365+int(y/4)-int(y/100)+int(y/400)-2472633;
        j=j*86400+$4*3600+$5*60+$6
        printf ("%d%s\n",j,$7)
    }'
}
date2milliseconds `echo "2010-08-18 18:59:19.073" | sed 's/-/ /g;s/:/ /g;s/\./ /g'`

#---------------------------
#毫秒转日期
function milliseconds2date {
    echo "$1" | awk '{
        i=$1; ms=i%1000; i=int(i/1000); ss=i%60; i=int(i/60); nn=i%60; i=int(i/60); hh=i%24; dd=int(i/24);

i=int(i/24);
        a=i+2472632; b=int((4*a+3)/146097); c=int((-b*146097)/4)+a;
        d=int((4*c+3)/1461); e=int((-1461*d)/4)+c; m=int((5*e+2)/153);
        dd=-int((153*m+2)/5)+e+1; mm=int(-m/10)*12+m+3; yy=b*100+d-4800+int(m/10);
        printf ("%4d-%02d-%02d %02d:%02d:%02d.%03d\n",yy,mm,dd,hh,nn,ss,ms)
    }'
}
milliseconds2date 1282157959073

 

实例:http://bbs.chinaunix.net/thread-1772999-1-1.html

% H 小时(00..23)
% I 小时(01..12)
% k 小时(0..23)
% l 小时(1..12)
% M 分(00..59)
% p 显示出AM或PM
% r 时间(hh:mm:ss AM或PM),12小时
% s 从1970年1月1日00:00:00到目前经历的秒数
% S 秒(00..59)
% T 时间(24小时制)(hh:mm:ss)
% X 显示时间的格式(%H:%M:%S)
% Z 时区 日期域
% a 星期几的简称( Sun..Sat)
% A 星期几的全称( Sunday..Saturday)
% b 月的简称(Jan..Dec)
% B 月的全称(January..December)
% c 日期和时间( Mon Nov 8 14:12:46 CST 1999)
% d 一个月的第几天(01..31)
% D 日期(mm/dd/yy)
% h 和%b选项相同
% j 一年的第几天(001..366)
% m 月(01..12)
% w 一个星期的第几天(0代表星期天)
% W 一年的第几个星期(00..53,星期一为第一天)
% x 显示日期的格式(mm/dd/yy)
% y 年的最后两个数字( 1999则是99)
% Y 年(例如:1970,1996等)
注意:只有超级用户才有权限使用date命令设置时间,一般用户只能使用date命令显示时间。


例子:
在每月第一天备份并压缩/etc目录的所有内容,存放在/root/bak目录里,且文件名为如下形式yymmdd_etc,yy为年,mm为

月,dd为日。Shell程序fileback存放在/usr/bin目录下。
#/bin/bash
#filebak
#file executable: chmod 755 filebak
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
bakdir="/root/bak/"
filename="`date +%y%m%d`_etc.tar.gz"
if [ ! -x "$bakdir" ];then
mkdir $bakdir
fi
cd $bakdir
tar cvfz $filename /etc
 或使用crontab -e 命令添加定时任务:
0 1 * * * /bin/sh /usr/bin/fileback


扩展功能
date 工具可以完成更多的工作,不仅仅只是打印出当前的系统日期。您可以使用它来得到给定的日期究竟是星期几,并得

到相对于当前日期的相对日期。了解某一天是星期几
GNU 对 date 命令的另一个扩展是 -d 选项,当您的桌上没有日历表时(UNIX 用户不需要日历表),该选项非常有用。使

用这个功能强大的选项,通过将日期作为引号括起来的参数提供,您可以快速地查明一个特定的日期究竟是星期几:
$ date -d "nov 22"
Wed Nov 22 00:00:00 EST 2006
$
在本示例中,您可以看到今年的 11 月 22 日是星期三。
所以,假设在 11 月 22 日召开一个重大的会议,您可以立即了解到这一天是星期三,而这一天您将赶到驻地办公室。
获得相对日期
d 选项还可以告诉您,相对于 当前日期若干天的究竟是哪一天,从现在开始的若干天或若干星期以后,或者以前(过去)

。通过将这个相对偏移使用引号括起来,作为 -d 选项的参数,就可以完成这项任务。
例如,您需要了解两星期以后的日期。如果您处于 Shell 提示符处,那么可以迅速地得到答案:
$ date -d ’2 weeks’
关于使用该命令,还有其他一些重要的方法。使用 next/last指令,您可以得到以后的星期几是哪一天:
$ date -d ’next monday’ (下周一的日期)
$ date -d next-day +%Y%m%d(明天的日期)或者:date -d tomorrow +%Y%m%d
$ date -d last-day +%Y%m%d(昨天的日期) 或者:date -d yesterday +%Y%m%d
$ date -d last-month +%Y%m(上个月是几月)
$ date -d next-month +%Y%m(下个月是几月)
使用 ago 指令,您可以得到过去的日期:
$ date -d ’30 days ago’ (30天前的日期)
您可以使用负数以得到相反的日期:
$ date -d ’dec 14 -2 weeks’ (相对:dec 14这个日期的两周前的日期)
$ date -d ’-100 days’ (100天以前的日期)
$ date -d ’50 days’(50天后的日期)
这个技巧非常有用,它可以根据将来的日期为自己设置提醒,可能是在脚本或 Shell 启动文件中,如下所示:
DAY=`date -d ’2 weeks’ +"%b %d"`
if test "`echo $DAY`" = "Aug 16"; then echo ’Product launch is now two weeks away!’; fi

shell中日期加减指定间隔单位
增加36小时:
$ a=`date +%Y-%m-%d`
$ b=`date +%Y-%m-%d -d "$a +36 hours"`

 

--------------------------------------------
shell中接收外部输入read
--------------------------------------------
如:
#!/bin/sh

echo "Please input the num (1~~10): "
read num
while [[ $num != 4 ]]
do
 if [ $num -lt 4 ]
done


--------------------------------------------
shell中获取当前文件路径
--------------------------------------------
selfpath=$(cd "$(dirname "$0")"; pwd)
echo $selfpath 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值