Chinaunix首页 | 论坛 | 博客
  • 博客访问: 256564
  • 博文数量: 78
  • 博客积分: 1465
  • 博客等级: 上尉
  • 技术积分: 972
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-28 13:46
文章分类

全部博文(78)

文章存档

2012年(1)

2011年(9)

2010年(68)

我的朋友

分类:

2010-01-11 00:56:29


这是自己在从学习shell到实际编一些小脚本的过程中,总结的一些shell知识,这些知识可能都能在其他地方看到,只是我把它们整合了一下,其中包含shell一些基本但又极其重要的部分,希望分享给大家作为编写shell时的手边备忘。
由于这些是从学习shell开始到现在,偶尔逐步追加的一些points,不连续,缺乏连贯性和逻辑性,限于本人level,难免其中有些小bug,若发现,还望指出。


shell三种流程控制结构(判断,分支,循环)

#判断

if [condition]

then

  cmd-list

elif [condition]

then

  cmd-list

else

  cmd-list

fi



注:elif [condition]; then 部分是可选的,是0个或多个关系:{elif [condition]; then}*

------------------------------------------------------我是分隔线------------------------------------------------

#分支

case var in

  1)cmd-list;;

  2)cmd-list;;

  3)cmd-list;;

  *)default-list;

esac



注:经常与它配套使用的还有一种类似控件选择分支的结构叫select,在此不多介绍了,常与case结合使用的一种特殊循环

------------------------------------------------------我是分隔线------------------------------------------------

#三种循环

for var in [value-list]

do

  cmd-list

done

------------------------------------------------------我是分隔线------------------------------------------------

while [condition]

do

  cmd-list

done

------------------------------------------------------我是分隔线------------------------------------------------

until [condition]

do

  cmd-list

done

------------------------------------------------------我是分隔线------------------------------------------------


流程控制是shell编程最基本的地方,在此再贴上这几种结构的例子:

#!/bin/sh

#if.sh file

echo "Input a number:"
read var

if [ -z $var ]
then
echo "var is empty, you input nothing"
elif [ $var -le 5 ]
then
echo "$var low equal than 5"
else
echo "$var greater than 5"
fi

------------------------------------------------------我是分隔线------------------------------------------------


#!/bin/sh

#case.sh file

case $# in

0) echo "No parameter.";;

1) echo "1 parameter:$1";;

2) echo "2 parameters:$1 $2";;

*) echo "More than 2 parameters:$@";;

esac

------------------------------------------------------我是分隔线------------------------------------------------

#!/bin/sh

#for.sh file

for var in A B C
do
echo "var is $var"
done

------------------------------------------------------我是分隔线------------------------------------------------

#!/bin/sh

#while.sh file

echo "Please input sth to echo:"

while read var
do
echo "$var"

done

------------------------------------------------------我是分隔线------------------------------------------------

#!/bin/sh

#until.sh file

echo "Please input sth to echo:"

until read var; [ -z "$var" ]
do
echo "$var";
done

------------------------------------------------------我是分隔线------------------------------------------------

0.shell变量
<1>等号两边不能有空格
<2>无数据类型概念,全部变量都理解为字符型
<3>变量替换
a=2334 # 整型.
let "a += 1" # 仅支持bash
echo "a = $a " # a = 2335
echo # 还是整型.
b=${a/23/BB} # 将"23"替换成"BB".
<4>'string' 单引号 (single quote, hard quote)
被单引号用括住的内容,将被视为单一字串。在引号内的代表变数的$符号,没有作用,也就是说,他被视为一般符号处理,防止任何变量替换。
heyyou=homeecho '$heyyou' # We get $heyyou

<5>"string" 双引号 (double quote, soft quote)
被双引号用括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。这点与单引数的处理方式不同。

1.函数间接引用传递,eg.
Say="Hello";
Hello="World!";

echo ${Say};
echo ${!Say};

输出:HelloWorld!

2.特殊变量
<1>$*变量: 存储命令行键入的全部参数$*=$1c$2c... c is the first char of IFS, if IFS is unset, c=' ', else if IFS is null, c is null too.
<2>$@变量: 命令行键入参数列表,注意与$*的区别$@="$1" "$2" ...
<3>$#变量: 存储命令行键入的参数个数
<4>$?变量: 退出状态存储的变量--系统自动(foreground pipeline)
<5>$-变量: current option flags
<6>$$变量: 存储shell的进程ID,如果在子进程中,该变量是其父shell的进程ID
<7>$!变量: 存储系统最后一个进程的id,eg. command &后台异步的进程(background & asynchronous)
<8>$0变量: 存储程序名
<9>${n}变量: 当传递的参数大于9的时候,必须使用这种方式来存取第10、11、…参数
<10>$_变量:

3.关于命令的执行
三种方法执行shell脚本:

<1>重定向给sh:

   $:sh < script.sh

<2>传递脚本文件给sh:

   $: sh script.sh

<3>直接执行script.h:

   $: chmod a+x script.sh

   $: ./script.sh

前两种方法的优点是,script.sh不一定是可执行的,最后一种却需要执行权限,优点是直观。

4.管道与标准输入输出:
需要参数的命令如果不指定参数,会从标准输入中获得输入;==>管道(主要第一个程序向标准输出写入输出,第二个程序从标准输入读取输入,就可以建立管道)

5.查找并替换
sed 's/Fine/FINE/g' test.txt > temp 修改保存在临时文件 (g为全局选项,否则只替换每行的第一个单词)
mv temp test.txt 更新原来文件
将test.txt 中的Fine替换为FINE。

6.从1到多个文件中搜索特定字符
grep -n 'shell' ed.cmd 从文件ed.cmd中找出shell所在的行(grep -i 参数忽略大小写 -v 不包含选项 -n 包含行数选项)

7.排序
sort 文件名
-u 去处重复行
-r 反序排序
-o 输出给同名文件 (直接保存到原文件中)
+1n 跳过一个字段(空格或制表符为单词间隔)
-t:以":"为跳跃间隔符
sed -n '/shell/p' ed.cmd 同结果
cat /etc/passwd | sort -t: -k3.1,3,4 -nr #逆序将用户ID排序

8.查找重复行
uniq test.txt
-d 找出重复的行
-c 统计重复行的次数

9.算数扩展运算
$((算数表达式/逻辑表达式))

10.引用
单引号(hard quote):shell严格的忽略全部单引号之间的字符
双引号(soft quote):shell不忽略$、反斜杠、反引号
反斜杠:等价单引号,对一个字符有效,适用于去掉特殊意义的字符,以免被shell解析(\c与'c' 等价)
放在一行最后,可以用于忽略换行符,也就是续行

11.命令替换
$()或者反引号``引起来,在子shell中执行命令,eg.
$(pwd) `pwd`

12.参数传递
从命令行接受参数,shell自动把从命令行中接受的第一个参数存放在第一个变量,第二个放第二个,……
从变量出现的位置开始算,同名算一个
shift命令每执行一次,变量的个数($#)减一,而变量值提前一位
当只有0个参数时,执行命令会报错
shift n:执行n次shift
eg. shift.sh
#!/bin/sh
while [ $# -ne 0 ]
do echo $1
done
结果:./shift.sh file1 file2 file3 将输出file1死循环
file1
file1
file1
......
eg. shift.sh
#!/bin/sh
while [ $# -ne 0 ]
do echo $1
shift #add this command
done
结果:./shift.sh file1 file2 file3 将依次输出参数
file1
file2
file3

13.垃圾桶
/dev/null
对于某些输出到标准输出的命令,如果不想输出,则可以重定向输出到系统垃圾桶中

14.逻辑操作符
! 逻辑非
-a 逻辑与
-o 逻辑或

15.空命令
:

16.格式化输出
printf命令
可以格式化的显示
printf "format" arg1 arg2 …
%表参数:
echo自动添加换行符,printf不会 "\n"可以进行换行

17.导出变量
export variables
父shell利用导出变量,能够将值复制给子shell,对所有后续子shell有效
export -p :清单

18.exec命令
exec program :启动一个新的shell代替当前的shell,所以这个语句后面的任何命令将无效(但可以用子shell去执行$exec, 如使用括号(exec pwd))

19.( … )和{ …; }结构
( … ) 子shell执行命令(可以没有空格,末尾可以没有分号)
{ …; } 当前shell执行命令(必须有空格,末尾必须有分号)

但命令串执行()和{}有区别:
A,()只是对一串命令重新开一个子shell进行执行
B,{}对一串命令在当前shell执行
C,()和{}都是把一串的命令放在括号里面,并且命令之间用;号隔开
D,()最后一个命令可以不用分号
E,{}最后一个命令要用分号
F,{}的第一个命令和左括号之间必须要有一个空格
G,()里的各命令不必和括号有空格
H,()和{}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令
20.深入参数
<1>参数替换
${parameter}
mv $file ${file}x :改名,给文件名增加X
${parameter:-value}:parameter 不为空,则替换值

${parameter:=value}:当parameter 不为空,不但使用value,而且赋值给parameter;不能用在位置参数上(也就是parameter不能使数字)
典型用法:测试导出变量是否设置了值,如果没有,就将它设为默认值

${parameter:?value}: 不为空替换,否则把value写入标准错误,然后退出

${parameter:+value}: 不为空替换,否则啥也不替换

<2>模式匹配

<3>set命令
设置各种shell选项,或者给位置参数$1,%2等重新赋值

<4>IFS变量

<5>readonly命令

<6>unset命令

21.函数
name () {command; … command;}
函数在定义shell中有效。
可以将一些常用的函数放在一个单独的文件中,然后通过点(.)来调用,那样,就可以在shell编程中使用。
<1>unset -f name
将函数定义去除
<2>return命令
exit会结束调用的shell,用return来结束函数运行

22.杂项
<1>eval命令
shell双次稍描命令行
<2>wait命令
wait process-id:省略进程号的话默认全部子进城
<3>trap命令
trap commands signals:
常用信号编号:
0-退出shell
1-挂起
2-中断(例如Delete、Ctrl+C键)
15-软件结束信号(默认由kill发出)
<4>深入I/O
<$-:关闭标准输出
>&-:关闭标准输入
<5>关于shell语句末的分号
shell中分号(;)仅起分隔语句的作用,如果一行仅有一条shell语句,则不用加分号,
但如果一行写有多条语句,则语句间要用分号隔开。比如if语句后面的then如果同if
在同一行就必须用;,eg. if [ -z $arg ]; then
<6>bash中有一个特性,通过declare a定义的a为整数



23.引用回溯命令的参数!^ !$ !!:n
!^: previous command's first arguments
!$: previous command's last arguments
!*: previous command's all arguments list
!!:0 --> previous command name
!!:1 --> previous command's first argument
!!:n --> previous n-th argument
阅读(1216) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~