回顾了下shell 编程的一些细节

回顾了一些细节

shell 的通配符扩展
 
?
[] 
[^xxxx] 
{aaa,bbb}      
 

子进程
more `grep -l POSIX *`
more $(grep -l POSIX *)
 

 
shell 变量的一些特性
 
赋值直接用变量名,获取内容需要加$
salutation=Hello
echo $salutation
 
读取输入
read salutation
 
关于shell 中的引号
#!/bin/bash
myvar="Hi there"
echo $myvar
echo "$myvar"
echo '$myvar'
echo \$myvar
 

shell 中的预定义变量
 
环境变量的概念:
    程序执行时,一些变量会根据环境设置中的值来进行初始化
$HOME
$PATH
$PS1
$PS2
$IFS            输入域分隔符,shell读取输入时分割单词的字符
$0            shell 脚本的名字
$#            传给脚本的参数个数
$$             shell脚本的进程号
$1 $2            第几个参数
$*                所有参数
 

shell 的条件判断
 
test 和 [] 
 
if test -f fred.c
then 
fi
 
if [ -f fred.c ]
then 
fi

test 可以使用的三类条件
 
1 字符串比较
string1 = string2
string1 != string2
-n string                字符串不为空则为真
-z string                字符串为空则为真
 
2 算术比较
expr1 -eq expr2
expr1 -ne expr2
expr1 -gt expr2
expr1 -ge expr2
expr1 -lt expr2
expr1 -le expr2
! expr                    表达式为假则为真
 
3 文件测试
-d file                文件是目录
-e file            如果文件存在
-f file                如果是普通文件
-g file            如果set-group-id 被设置
-r file            如果文件可读
-s file            未果文件大小不为0
-u file            如果set-user-id 被设置
-w file            如果文件可写
-x file            如果文件可执行
 

通过read获取的值,引用时最好用双引号引起来,这样的话,直接回车变量就是空字符串
 

输出不换行
有些系统不支持用echo -e 
bash 可以用 echo -n 
最好用printf
 
 

shell 中的控制结构
 
1 if
echo "yes or no"
read timeofday
if [ "$timeofday" = "yes" ]; then
    echo "good"
else 
    echo "wrong"
fi
exit 0
 
2 elif
echo "yes or no"
read timeofday
if [ "$timeofday" = "yes" ]
then
    echo "Good morning"
elif [ "$timeofday" = "no" ]; then
    echo "good"
else
    echo "sorry"
    exit 1
fi
exit 0
 
3 for
for foo in bar fud 43
do 
    echo $foo
done
exit 0
 
for file in $(ls f*.sh); do
    cat $file
done
exit 0
 
4 while
echo "Enter password"
read trythis
while [ "$trythis" != "secret" ]; do
    echo "Sorry, try again"
    read trythis
done
exit 0
 
5 until 反复执行,知道为真
监控某个用户登陆
until who | grep "$1" > /dev/null
do
    sleep 60
done
echo -e '\a'
echo " *** $1 has logged in *** "
exit 0
 
6 case 语句
 
基础用法
echo "yes or no"
read timeofday
case "$timeofday" in
    yes) echo "Good morning";;
    no ) echo "good afternoon";;
    y  ) echo "good morning";;
    n  ) echo "good afternoon";;
    *  ) echo "sorry";;
esac
exit 0
 
合并匹配模式
echo "yes or no"
read timeofday
case "$timeofday" in
    yes | y | Yes | YES ) echo "morning";;
    n* | N* )             echo "afternoon";;
    * )                   echo "sorry";;
esac
exit 0
 
执行多条语句
echo "yes or no"
read timeofday
case "$timeofday" in 
    yes | Y | Yes | YES )
        echo "morning"
        echo "up"
        ;;
    [nN]* )
        echo "good afternoon"
        ;;
    *)
        echo "sorry"
        echo no"
        exit 1
        ;;
esac
exit 0
 
7 and 和 or
短路逻辑
 
and && 
touch file_one
rm -f file_two
if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo " there"
then 
    echo "in if"
else
    echo "in else"
fi
exit 0
 
or ||
 
 
8 语句块
 
在只允许单个语句的地方,比如(and or 列表) ,可以用花括号构造一个语句块
 

shell 中的函数
foo()  {
    echo "function"
}
echo "start"
foo
echo "end"
exit 0
 
函数中的局部变量
shell 中的函数默认会使用全局变量
sample_text="global variable"
foo() {
    local sample_text="local variable"
    echo "function foo executing"
    echo $sample_text
}
echo "start"
echo $sample_text
foo
echo "end"
echo $sample_text
exit 0
 
函数参数传递与返回值
#!/bin/bash
yes_or_no() {
    echo "Is your name $* ?"
    while true
    do
        echo -n "Enter yes or no: "
        read x
        case "$x" in
            y | yes ) return 0;;
            n | no ) return 1;;
            * )     echo "answer yes or no"
        esca
    done
}
 
echo "Original paramers are $*"
if yes_or_no "$1"
then 
    echo "Hi $1, nice name"
else
    echo "Never mind"
fi
exit 0
 
 

 
shell 提供的命令
 
1 break
2 :             等价于true
3 continue
 
4 .     在当前shell中执行命令
. ./shell_script
source ./shell_script
 
5 echo 
建议在现代shell中用printf
 
6 eval
foo=10
x=foo
eval y='$'$x
echo $y
 
# 结果为10
 
7 exec
exec典型用法时将当前shell替换为一个不同程序,脚本后面的代码不会执行
exec wall "Thanks for all the fish"
 
另一种用法是修改当前文件描述符
exec 3< afile
打开文件描述符3,从afile读取数据
 
8 exit
 
9 export 
export命令将作为它参数的变量导出到子shell中
 
10 expr
expr 将它的参数当作数学表达式运算
x=10
x=`expr $x + 1`
 
expr 支持的运算符
expr1 | expr2        如果expr1非零,则等于exp1,否则等于expr2
expr1 & expr2        只要有一个表达式为零,则等于零,否则等于expr1
expr1 = expr2
expr1 > expr2    >=  < <= != + - * / %
 
expr 常被替换为 $((…))
 
11 printf
printf "%s\n" hello
printf "%s %d\t %s" "Hi There" 15 people
 
12 return
使函数返回,如果函数没有return,则返回值是最后一条命令的退出码
 
13 set
set 用来为shell设置参数变量
 
14 shift命令
shift把所有参数变量左移一个位置,使$2变成 $1,以此类推
 
15 trap
trap用于指定在接收到信号后要采取的行动
 
trap -l 查看信号编号和关联的名称
 
trap command signal
 
重置某个信号的处理方式,command -
忽略某个信号 command 设置为空字符串’'
 
#!/bin/bash
trap "rm -f /tmp/my_tmp_file_$$" INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
 
echo "press interrupt ( C-c ) to interrupt …."
while [ -f /tmp/my_tmp_file_$$ ]; do
    echo File exists
    sleep 1
done
echo The file no longer exists
 
trap "" INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
 
echo "press interrupt (C-c) to interrupt ….."
while [ -f /tmp/my_tmp_file_$$ ]; do
    echo File exists
    sleep 1
done
 
echo we never get here
exit 0
 
16 unset
unset 用来从环境中删除变量或函数,不能删除shell本身定义的只读变量

 
17 find
 
find [path] [option] [tests] [actions]
 
基本用法
find / -name test -print
-print 是默认action
 
不搜索挂载的其他文件系统的目录
find / -mount -name test -print     
 
在当前目录下搜索比文件while2新的文件
find . -newer while2 -type f -print
 
组合测试
find . \( -name "_*" -or -newer while2 \) -type f -print
 
执行一条命令,动作必须用\;字符对结束
find . -newer while2 -type f -exec ls -l {} \; 
 
18 grep
 
grep [options] PATTERN [FILES]
如果没有提供文件名,grep会使用标准输入
 
grep in words.txt
grep -c in words.txt words2.txt       输出匹配的统计
grep -c -v in words.txt words2.txt         -v 取反
 

grep 中的正则表达式
 
常用的特殊字符
^
$
.
[]    里面是范围[a-z]  范围前加^表示反向字符
 
在方括号内可以使用的一些有用的特殊匹配模式,比如[[:alnum:]]
[:alnum:]
[:alpha:]
[:ascii:]
[:blank:]    空格或制表符
[:cntrl:]
[:digit:]
[:graph:]
[:graph:]
[:lower:]
[:print:]
[:punct:]
[:space:]   空白字符,包括垂直制表符
[:upper:]
[:xdigit:]        十六进制数字
 
如果指定了-E可以用扩展匹配,但是需要加\
?
+
{n}
{n,}
{n,m}
 
查找以字母e结尾的行
grep e$ words2.txt
 
查找以字母a结尾的单词
grep a[[:blank:]] words2.txt
 
查找以Th开头的,由三个字母组成的单词
grep Th.[[:space:]] words2.txt
 
查找长度为10,都由小写字母组成的单词
grep -E [a-z]\{10\} words2.txt
 

shell 中获得命令执行结果
whoisthere=$(who)
echo $whoisthere
 
如果需要把命令输出转换为参数,并作为另一个程序的参数,可以用xargs
 

expr 的新扩展 $((..))
x=0
while [ "$x" -ne 10 ]; do
    echo $x
    x=$(($x+1))
done
exit 0
 

参数扩展
 
基本用法
for i in 1 2
do 
    my_secret_process ${i}_tmp
done
 
参数扩展
${param:-default}   如果param为空,把它设置为default的值
${#param}            给出param的长度
${param%word}       从param尾部开始删除与word匹配的最小部分,返回剩余部分
${param%%word}           尾部  最长
${param#word}        头部 最小
${param##word}        头部 最长
 
 
unset foo
echo ${foo:-bar}       # bar
 
foo=fud
echo ${foo:-bar}       # fud
 
foo=/usr/bin/X11/startx
echo ${foo#*/}         # usr/bin/X11/startx
echo ${foo##*/}         # startx
 
bar=/usr/local/etc/local/networks
echo ${bar%local*}         # /usr/local/etc
echo ${bar%%local*}        # /usr/
 
批量转换GIF为JPEG
for image in *.gif
do
    cjpeg $image > ${image%%gif}jpg
done
 

here 文档
ed a_text_file <<!FunkyStuff!
3
d
.,\$s/is/was/
w
q
!FunkyStuff!
 
exit 0
 

 
shell 脚本调试
 
1 只检查语法错误,不执行命令
sh -n <script>
 
set -o noexec
set -n
 
2 执行命令前回显它们
sh -v <script>
 
set -o verbose
set -v
 
3 执行完命令后回显它们
sh -x <script>
 
set -o xtrace
set -x
 
4 如果使用了未定义的变量,就给出错误消息
sh -u <script>
 
set -o nounset
set -u
 
通过捕获EXIT信号,查看脚本退出时的状态
trap "echo Exiting: critical variable=$critical_variable" EXIT
 
posted @ 2019-11-30 20:43  君莫笑hhhhhh  阅读(216)  评论(0编辑  收藏  举报