📄 shell编程.txt
字号:
1 #!/bin/bash
2 #background-loop.sh
3
4 for i in 1 2 3 4 5 6 7 8 9 10 #第一个循环
5 do
6 echo -n "$i"
7 done& #在后台运行这个循环
8 #在第2个循环之后,将在某些时候执行.
9
10 echo #这个'echo'某些时候将不会显示.
11
12 for i in 11 12 13 14 15 16 17 18 19 20 #第二个循环
13 do
14 echo -n "$i"
15 done
16
17 echo #这个'echo'某些时候将不会显示.
18
19 #--------------------------------------------------------
20
21 #期望的输出应该是
22 #1 2 3 4 5 6 7 8 9 10
23 #11 12 13 14 15 16 17 18 19 20
24
25 #然而实际的结果有可能是
26 #11 12 13 14 15 16 17 18 19 20
27 #1 2 3 4 5 6 7 8 9 10 bozo $
28 #(第2个'echo'没执行,为什么?)
29
30 #也可能是
31 #1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
32 #(第1个'echo'没执行,为什么?)
33
34 #非常少见的执行结果,也有可能是:
35 #11 12 13 1 2 3 4 5 6 7 8 9 10 14 15 16 17 18 19 20
36 #前台的循环先于后台的执行
37
38 exit 0
39
40 # Nasimuddin Ansari 建议加一句 sleep 1
41 #+ 在 6行和14行的 echo -n "$i"之后加
42 #+ 将看到一些乐趣
################################End Script#########################################
注意:在一个脚本内后台运行一个命令,有可能造成这个脚本的挂起,等待一个按键
响应.幸运的是,我们可以在Example 11-24附近,看到这个问题的解决办法.
&& 与-逻辑操作.
- 选项,前缀.在所有的命令内如果想使用选项参数的话,前边都要加上"-".
COMMAND -[Option1][Option2][...]
ls -al
sort -dfu $filename
set -- $variable
1 if [ $file1 -ot $file2 ]
2 then
3 echo "File $file1 is older than $file2."
4 fi
5
6 if [ "$a" -eq "$b" ]
7 then
8 echo "$a is equal to $b."
9 fi
10
11 if [ "$c" -eq 24 -a "$d" -eq 47 ]
12 then
13 echo "$c equals 24 and $d equals 47."
14 fi
- 用于重定向 stdin 或 stdout.
################################Start Script#######################################
1 (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)
2 # 从一个目录移动整个目录树到另一个目录
3 # [courtesy Alan Cox <a.cox@swansea.ac.uk>, with a minor change]
4
5 # 1) cd /source/directory 源目录
6 # 2) && 与操作,如果cd命令成功了,那么就执行下边的命令
7 # 3) tar cf - . 'c'创建一个新文档,'f'后边跟'-'指定目标文件作为stdout
8 # '-'后边的'f'(file)选项,指明作为stdout的目标文件.
9 # 并且在当前目录('.')执行.
10 # 4) | 管道...
11 # 5) ( ... ) 一个子shell
12 # 6) cd /dest/directory 改变当前目录到目标目录.
13 # 7) && 与操作,同上.
14 # 8) tar xpvf - 'x'解档,'p'保证所有权和文件属性,
15 # 'v'发完整消息到stdout
16 # 'f'后边跟'-',从stdin读取数据
17 #
18 # 注意:'x' 是一个命令, 'p', 'v', 'f' 是选项.
19 # Whew!
20
21
22
23 # 更优雅的写法应该是
24 # cd source/directory
25 # tar cf - . | (cd ../dest/directory; tar xpvf -)
26 #
27 # 当然也可以这么写:
28 # cp -a /source/directory/* /dest/directory
29 # 或者:
30 # cp -a /source/directory/* /source/directory/.[^.]* /dest/directory
31 # 如果在/source/directory中有隐藏文件的话.
################################End Script#########################################
################################Start Script#######################################
1 bunzip2 linux-2.6.13.tar.bz2 | tar xvf -
2 # --未解压的tar文件-- | --然后把它传递到"tar"中--
3 # 如果 "tar" 没能够正常的处理"bunzip2",
4 # 这就需要使用管道来执行2个单独的步骤来完成它.
5 # 这个练习的目的是解档"bzipped"的kernel源文件.
################################End Script#########################################
注意:在上边这个例子中'-'不太象是bash的操作符,而更像是tar的参数.
bash$echo "whatever" | cat -
whatever
在需要一个文件名的地方,-重定向输出到stdout(如在tar和cf命令中),或者从
stdin中接受输入,而不是从一个文件中接受输入.这是在管道中作为一个过滤
器,来使用文件定位工具的一种办法.
bash$file
用法: file [-bciknvzl] [-f namefile] [-m magicfiles] file...
上边这个例子file将会出错,提示你如何使用file命令.
添加一个"-"将得到一个更有用的结果.这将使得shell等待用户输入.
bash$file -
abc
standard input: ASCII text
bash$file -
#!/bin/bash
standard input: Bourn-Again shell script tesxt executable
现在命令从stdin中接受了输入,并分析它.
"-"常用于管道后边的命令,具体参看33.7节,来看使用技巧.
使用diff命令来和另一个文件的一部分进行比较.
grep Linux file1 | diff file2 -
最后,一个真实世界的使用tar命令的例子.
Example 3-4. 备份最后一天所有修改的文件.
################################Start Script#######################################
1 #!/bin/bash
2
3 # 在一个"tarball"中(经过tar和gzip处理过的文件)
4 #+ 备份最后24小时当前目录下d所有修改的文件.
5
6 BACKUPFILE=backup-$(date +%m-%d-%Y)
7 # 在备份文件中嵌入时间.
8 # Thanks, Joshua Tschida, for the idea.
9 archive=${1:-$BACKUPFILE}
10 # 如果在命令行中没有指定备份文件的文件名,
11 #+ 那么将默认使用"backup-MM-DD-YYYY.tar.gz".
12
13 tar cvf - `find . -mtime -1 -type f -print` > $archive.tar
14 gzip $archive.tar
15 echo "Directory $PWD backed up in archive file \"$archive.tar.gz\"."
16
17
18 # Stephane Chazelas指出上边代码,
19 #+ 如果在发现太多的文件的时候,或者是如果文件
20 #+ 名包括空格的时候,将执行失败.
21
22 # Stephane Chazelas建议使用下边的两种代码之一
23 # -------------------------------------------------------------------
24 # find . -mtime -1 -type f -print0 | xargs -0 tar rvf "$archive.tar"
25 # 使用gnu版本的find.
26
27
28 # find . -mtime -1 -type f -exec tar rvf "$archive.tar" '{}' \;
29 # 对于其他风格的UNIX便于移植,但是比较慢.
30 # -------------------------------------------------------------------
31
32
33 exit 0
################################End Script#########################################
注意:以"-"开头的文件名在使用"-"作为重定向操作符的时候,可能会产生问题.
应该写一个脚本来检查这个问题,并给这个文件加上合适的前缀.如:
./-FILENAME, $PWD/-FILENAME,或$PATHNAME/-FILENAME.
如果变量的值以"-"开头,可能也会引起问题.
1 var="-n"
2 echo $var
3 #具有"echo -n"的效果了,这样什么都不会输出的.
- 之前工作的目录."cd -"将回到之前的工作目录,具体请参考"$OLDPWD"环境变量.
注意:一定要和之前讨论的重定向功能分开,但是只能依赖上下文区分.
- 算术减号.
= 算术等号,有时也用来比较字符串.
1 a=28
2 echo $a # 28
+ 算术加号,也用在正则表达式中.
+ 选项,对于特定的命令来说使用"+"来打开特定的选项,用"-"来关闭特定的选项.
% 算术取模运算.也用在正则表达式中.
~ home目录.相当于$HOME变量.~bozo是bozo的home目录,并且ls ~bozo将列出其中的
内容. ~/就是当前用户的home目录,并且ls ~/将列出其中的内容,如:
bash$ echo ~bozo
/home/bozo
bash$ echo ~
/home/bozo
bash$ echo ~/
/home/bozo/
bash$ echo ~:
/home/bozo:
bash$ echo ~nonexistent-user
~nonexistent-user
~+ 当前工作目录,相当于$PWD变量.
~- 之前的工作目录,相当于$OLDPWD内部变量.
=~ 用于正则表达式,这个操作将在正则表达式匹配部分讲解,只有version3才支持.
^ 行首,正则表达式中表示行首."^"定位到行首.
控制字符
修改终端或文本显示的行为.控制字符以CONTROL + key组合.
控制字符在脚本中不能正常使用.
Ctl-B 光标后退,这应该依赖于bash输入的风格,默认是emacs风格的.
Ctl-C Break,终止前台工作.
Ctl-D 从当前shell登出(和exit很像)
"EOF"(文件结束符).这也能从stdin中终止输入.
在console或者在xterm window中输入的时候,Ctl-D将删除光标下字符.
当没有字符时,Ctrl-D将退出当前会话.在xterm window也有关闭窗口
的效果.
Ctl-G beep.在一些老的终端,将响铃.
Ctl-H backspace,删除光标前边的字符.如:
1 #!/bin/bash
2 # 在一个变量中插入Ctl-H
3
4 a="^H^H" # 两个 Ctl-H (backspaces).
5 echo "abcdef" # abcdef
6 echo -n "abcdef$a " # abcd f
7 # 注意结尾的空格 ^ ^ 两个 twice.
8 echo -n "abcdef$a" # abcdef
9 # 结尾没有空格 没有 backspace 的效果了(why?).
10 # 结果并不像期望的那样
11 echo; echo
Ctl-I 就是tab键.
Ctl-J 新行.
Ctl-K 垂直tab.(垂直tab?新颖,没听过)
作用就是删除光标到行尾的字符.
Ctl-L clear,清屏.
Ctl-M 回车
################################Start Script#######################################
1 #!/bin/bash
2 # Thank you, Lee Maschmeyer, for this example.
3
4 read -n 1 -s -p $'Control-M leaves cursor at beginning of this line. Press Enter. \x0d'
5 #当然,'0d'就是二进制的回车.
6 echo >&2 # '-s'参数使得任何输入都不将回显出来
7 #+ 所以,明确的重起一行是必要的.
8
9 read -n 1 -s -p $'Control-J leaves cursor on next line. \x0a'
10 echo >&2 # Control-J 是换行.
11
12 ###
13
14 read -n 1 -s -p $'And Control-K\x0bgoes straight down.'
15 echo >&2 # Control-K 是垂直制表符.
16
17 # 关于垂直制表符效果的一个更好的例子见下边:
18
19 var=$'\x0aThis is the bottom line\x0bThis is the top line\x0a'
20 echo "$var"
21 # 这句与上边的例子使用的是同样的办法,然而:
22 echo "$var" | col
23 # 这将造成垂直制表符右边的部分在左边部分的上边.
24 # 这也解释了为什么我们要在行首和行尾加上一个换行符--
25 #+ 来避免一个混乱的屏幕输出.
26
27 # Lee Maschmeyer的解释:
28 # ---------------------
29 # In the [first vertical tab example] . . . the vertical tab
29 # 在这里[第一个垂直制表符的例子中] . . . 这个垂直制表符
30 #+ makes the printing go straight down without a carriage return.
31 # This is true only on devices, such as the Linux console,
32 #+ that can't go "backward."
33 # The real purpose of VT is to go straight UP, not down.
34 # It can be used to print superscripts on a printer.
34 # 它可以用来在一个打印机上打印上标.
35 # col的作用,可以用来模仿VT的合适的行为.
36
37 exit 0
################################End Script#########################################
Ctl-Q 继续(等价于XON字符),这个继续的标准输入在一个终端里
Ctl-S 挂起(等价于XOFF字符),这个被挂起的stdin在一个终端里,用Ctl-Q恢复
Ctl-U 删除光标到行首的所有字符,在某些设置下,删除全行.
Ctl-V 当输入字符时,Ctl-V允许插入控制字符.比如,下边2个例子是等价的
echo -e '\x0a'
echo <Ctl-V><Ctl-J>
Ctl-V在文本编辑器中十分有用,在vim中一样.
Ctl-W 删除当前光标到前边的最近一个空格之间的字符.
在某些设置下,删除到第一个非字母或数字的字符.
Ctl-Z 终止前台工作.
空白部分
分割命令或者是变量.包括空格,tab,空行,或任何它们的组合.
在一些特殊情况下,空白是不允许的,如变量赋值时,会引起语法错误.
空白行在脚本中没有效果.
"$IFS",对于某些命令输入的特殊变量分割域,默认使用的是空白.
如果想保留空白,使用引用.
注意事项:
[1] shell做大括号的命令扩展.但是命令本身需要对扩展的结果作处理.
[2] 例外:在pipe中的一个大括号中的代码段可能运行在一个子shell中.
1 ls | { read firstline; read secondline; }
2 # 错误,在打括号中的代码段,将运行到子shell中.
3 #+ 所以ls的输出将不能传递到代码块中.
4 echo "First line is $firstline; second line is $secondline" # 不能工作
5
6 # Thanks, S.C.
[3] 换行符也被认为是空白.这也解释了为什么一个空行也会被认为是空白.
第4章 变量和参数的介绍
======================
4.1 变量替换
------------
$ 变量替换操作符
只有在变量被声明,赋值,unset或exported或者是在变量代表一个signal的时候,
变量才会是以本来的面目出现在脚本里.变量在被赋值的时候,可能需要使用"=",
read状态或者是在循环
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -