博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux sh/bash 编程常用
阅读量:4036 次
发布时间:2019-05-24

本文共 6287 字,大约阅读时间需要 20 分钟。

本系列针对Bash Shell,其他的比较流行的Shell还有Korn shell (ksh)和"Tenex C shell" (tcsh

)。

一 简单过程
1)可以使用任意一种文字编辑器,比如nedit、kedit、emacs、vi等来编写shell脚本。ubuntu中可以使用gedit,notpad++也不错啊。
2)文件必须以#!/bin/sh开始。符号#!用来告诉系统那个shell来执行该脚本的程序,系统中可以有多个shell,例如使用/bin/sh,/bin/bash。
3)编辑结束并保存后,如果要执行该脚本,必须先使其可执行,使用命令chmod +x filename。
4)此后在该脚本所在目录下,输入 ./filename 即可执行该脚本。
5)最简单的调试方法当然是使用echo命令。你可以在任何怀疑出错的地方用echo打印变量值。
6)可以用sh -x strangescript来调试。
7)可以使用sh -n your_script来检查语法,不执行。
8)以# 开始的行表示注释,直到该行的结束。
二 命令
可以使用所有的Unux的命令。
三 变量
Shell编程中,使用变量无需事先声明,同时变量名的命名须遵循如下规则:1. 首个字符必须为字母(a-z,A-Z)2. 中间不能有空格,可以使用下划线(_)3. 不能使用标点符号 4. 不能使用bash里的关键字(可用help命令查看保留关键字)。
要给变量赋值时,可以这么写:变量名=值, 等号两边均不能有空格存在。为了避免混淆,可以使用{}给变量,如${num}。
四 管道/重定向
*  管道 (|) :将一个命令的输出作为另外一个命令的输入 :grep "hello" file.txt | wc -l 。 上述命令会在file.txt中搜索包含有”hello”的行并计算行数,这里grep命令的输出成了wc命令的
输入。
* 重定向:将命令的结果输出到文件,而不是标准输出(屏幕) > 写入文件并复盖旧文件,>> 加到文件的尾部,保留旧文件内容。
* 反短斜线:反短斜线可以将一个命令的输出作为其它命令的命令行参数。find . -mtime -1 -type f -print。上述命令可以查找过去24小时(-mtime –2则表示过去48小时)内修改过的文件。如果您想将所有查找到的文件打一个包,则可以使用以下脚本:
#!/bin/sh
# The ticks are backticks (`) not normal quotes  ('):
tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`
* 单引号‘’:功能则最强。当你把字符串用单引号括起来时,外壳将忽视所有单引号中的特殊字符。
* 双引号“”:双引号的功能最弱。当你把字符串用双引号括起来时,外壳将忽略字符串中的空格,但其他的字符都将继续起作用。双引号在将多于一个单词的字符串赋给一个变量时尤其有用。
* 反斜杠\:反斜杠的功能和单引号一样,只是反斜杠每次只能使一个字符发生转义,而不是使整个字符串发生转义。
五 特殊字符
• 有些变量在启动外壳时就已经存在于系统中,你可以使用这些系统变量,并且可以赋予
新值:
$HOME 用户自己的目录。
$ PATH 执行命令时所搜寻的目录。
$TZ 时区。
$MAILCHECK 每隔多少秒检查是否有新的邮件。
$ P S 1 在外壳命令行的提示符。
$ P S 2 当命令尚未打完时,外壳要求再输入时的提示符。
$ M A N PATHman 指令的搜寻路径。
• 有些变量在执行外壳程序时系统就设置好了,并且你不能加以修改:
$ # 存储外壳程序中命令行参数的个数。
$ ? 存储上一个执行命令的返回值。
$ 0 存储外壳程序的程序名。
$ * 存储外壳程序的所有参数。
$ @ 存储所有命令行输入的参数,分别表示为(“$ 1” “$ 2” . . . )。shift 命令用来将存储在位置参数中的当前值左移一个位置。
$ $ 存储外壳程序的P I D。
$ ! 存储上一个后台执行命令的P I D。
六 关键字
1)if
if [ expression ]
then
commands
elif [ expression2 ]
then
commands
else
commands
fi
2)条件,条件之间可以使用&& 和||

-b file            若文件存在且是一个块特殊文件,则为真

-c file            若文件存在且是一个字符特殊文件,则为真
-d file           
若文件存在且是一个目录,则为真
-e file           
若文件存在,则为真
-f file           
若文件存在且是一个规则文件,则为真
-g file           
若文件存在且设置了SGID位的值,则为真
-h file           
若文件存在且为一个符合链接,则为真
-k file           
若文件存在且设置了"sticky"位的值
-p file           
若文件存在且为一已命名管道,则为真
-r file           
若文件存在且可读,则为真
-s file           
若文件存在且其大小大于零,则为真
-u file           
若文件存在且设置了SUID位,则为真
-w file           
若文件存在且可写,则为真
-x file           
若文件存在且可执行,则为真
-o file           
若文件存在且被有效用户ID所拥有,则为真

-z string          string长度为0,则为真

-n string          string长度不为0,则为真
string1 = string2 
若两个字符串相等,则为真
string1 != string2
若两个字符串不相等,则为真

int1 -eq int2      int1等于int2,则为真

int1 -ne int2      int1不等于int2,则为真
int1 -lt int2     
int1小于int2,则为真
int1 -le int2     
int1小于等于int2,则为真
int1 -gt int2     
int1大于int2,则为真
int1 -ge int2     
int1大于等于int2,则为真

!expr              expr为假则复合表达式为真。expr可以是任何有效的测试表达式

expr1 -a expr2     expr1expr2都为真则整式为真
expr1 -o expr2    
expr1expr2有一个为真则整式为真
3)case
case string1 in
str1 )
commands ; ;
str2 )
commands ; ;
* )
commands ; ;
esac
4)for
for var1 in list
do
commands
done
5)while
while expression
do
statements
done
6)until
until expression
do
commands
done
7)select
select menuitem [in list_of_items]
do
commands
done

 

七 子函数

fname () {
shellcommands
}
调用fname [parm1 parm2 parm3 ...]

 

实例:

http://intuitive.com/wicked/scripts/053-verifycron.txt

https://github.com/djura-san/100-shell-script-examples/blob/master/053-verifycron.sh

#!/bin/sh
 
# verifycron - script checks a crontab file to ensure that it's
#    formatted properly.  Expects standard cron notation of
#       min hr dom mon dow CMD   
#    where min is 0-59, hr 0-23, dom is 1-31, mon is 1-12 (or names)
#    and dow is 0-7 (or names).  Fields can have ranges (a-e), lists
#    separated by commas (a,c,z), or an asterisk. Note that the step
#    value notation of Vixie cron is not supported (e.g., 2-6/2).
 
 
validNum()
{
  
# return 0 if valid, 1 if not. Specify number and maxvalue as args
  
num=$1   max=$2
 
  
if
[
"$num"
=
"X"
] ; then
    
return
0
  
elif [ ! -z $(echo
$num
| sed
's/[[:digit:]]//g'
) ] ; then
    
return
1
  
elif [
$num
-lt 0 -o
$num
-gt
$max
] ; then
    
return
1
  
else
    
return
0
  
fi
}
 
validDay()
{
  
# return 0 if a valid dayname, 1 otherwise
 
  
case $(echo $1 |
tr
'[:upper:]'
'[:lower:]'
) in
    
sun*|mon*|tue*|wed*|thu*|fri*|sat*)
return
0 ;;
    
X)
return
0 ;;
# special case - it's an "*"
    
*)
return
1
  
esac
}
 
validMon()
{
  
# return 0 if a valid month name, 1 otherwise
 
   
case $(echo $1 |
tr
'[:upper:]'
'[:lower:]'
) in
     
jan*|feb*|mar*|apr*|may|jun*|jul*|aug*)
return
0       ;;
     
sep*|
oct
*|nov*|dec*)           
return
0       ;;
     
X)
return
0 ;;
# special case, it's an "*"
     
*)
return
1    ;;
   
esac
}
 
fixvars()
{
  
# translate all '*' into 'X' to bypass shell expansion hassles
  
# save original as "sourceline" for error messages
 
  
sourceline=
"$min $hour $dom $mon $dow $command"
   
min=$(echo
"$min"
|
tr
'*'
'X'
)
  
hour=$(echo
"$hour"
|
tr
'*'
'X'
)
   
dom=$(echo
"$dom"
|
tr
'*'
'X'
)
   
mon=$(echo
"$mon"
|
tr
'*'
'X'
)
   
dow=$(echo
"$dow"
|
tr
'*'
'X'
)
}
 
if
[ $
# -ne 1 ] || [ ! -r $1 ] ; then
  
echo
"Usage: $0 usercrontabfile"
>&2;
exit
1
fi
 
lines=0  entries=0  totalerrors=0
 
while
read
min hour dom mon dow command
do
  
lines=
"$(( $lines + 1 ))"
  
errors=0
   
  
if
[ -z
"$min"
-o
"${min%${min#?}}"
=
"#"
] ; then
    
continue   
# nothing to check
  
elif [ ! -z $(echo ${min%${min
#?}} | sed 's/[[:digit:]]//') ] ;  then
    
continue   
# first char not digit: skip!
  
fi
 
  
entries=
"$(($entries + 1))"
 
  
fixvars
 
  
#### Broken into fields, all '*' replaced with 'X'
  
# minute check
 
  
for
minslice in $(echo
"$min"
| sed
's/[,-]/ /g'
) ;
do
    
if
! validNum
$minslice
60 ; then
      
echo
"Line ${lines}: Invalid minute value \"$minslice\""
      
errors=1
    
fi
  
done
 
  
# hour check
   
  
for
hrslice in $(echo
"$hour"
| sed
's/[,-]/ /g'
) ;
do
    
if
! validNum
$hrslice
24 ; then
      
echo
"Line ${lines}: Invalid hour value \"$hrslice\""
      
errors=1
    
fi
  
done
 
  
# day of month check
 
  
for
domslice in $(echo
$dom
| sed
's/[,-]/ /g'
) ;
do
    
if
! validNum
$domslice
31 ; then
      
echo
"Line ${lines}: Invalid day of month value \"$domslice\""
      
errors=1
    
fi
  
done
 
  
# month check
 
  
for
monslice in $(echo
"$mon"
| sed
's/[,-]/ /g'
) ;
do
    
if
! validNum
$monslice
12 ; then
      
if
! validMon
"$monslice"
; then
        
echo
"Line ${lines}: Invalid month value \"$monslice\""
        
errors=1
      
fi
    
fi
  
done
 
  
# day of week check
 
  
for
dowslice in $(echo
"$dow"
| sed
's/[,-]/ /g'
) ;
do
    
if
! validNum
$dowslice
7 ; then
      
if
! validDay
$dowslice
; then
        
echo
"Line ${lines}: Invalid day of week value \"$dowslice\""
        
errors=1
      
fi
    
fi
  
done
 
  
if
[
$errors
-gt 0 ] ; then
    
echo
">>>> ${lines}: $sourceline"
    
echo
""
    
totalerrors=
"$(( $totalerrors + 1 ))"
  
fi
done < $1
 
echo
"Done. Found $totalerrors errors in $entries crontab entries."
 
exit
0

  

完!

 

转载地址:http://eandi.baihongyu.com/

你可能感兴趣的文章
python:如何将excel文件转化成CSV格式
查看>>
Django 的Error: [Errno 10013]错误
查看>>
机器学习实战之决策树(一)
查看>>
机器学习实战之决策树二
查看>>
[LeetCode By Python]7 Reverse Integer
查看>>
[leetCode By Python] 14. Longest Common Prefix
查看>>
[LeetCode By Python]118. Pascal's Triangle
查看>>
[LeetCode By Python]121. Best Time to Buy and Sell Stock
查看>>
[LeetCode By Python]122. Best Time to Buy and Sell Stock II
查看>>
[LeetCode By Python]125. Valid Palindrome
查看>>
[LeetCode By Python]136. Single Number
查看>>
[LeetCode By MYSQL] Combine Two Tables
查看>>
[Leetcode BY python ]190. Reverse Bits
查看>>
Android下调用收发短信邮件等(转载)
查看>>
Android中电池信息(Battery information)的取得
查看>>
SVN客户端命令详解
查看>>
Android/Linux 内存监视
查看>>
Linux系统信息查看
查看>>
用find命令查找最近修改过的文件
查看>>
Android2.1消息应用(Messaging)源码学习笔记
查看>>