第二章 shell程序设计。
之前也有过了解linux shell编程,这都是随便瞟过,想想也挺后悔。这么强大的工具,主要是这语法有点恶心。忍忍吧。毕竟要重新学,就学得认真点。
本章将学习:
1.什么是shell
2.基本思路
3.微妙的语法:变量,条件判断和程序控制。
4.命令列表。
5.函数
6.here文档
7.调试
8.grep命令和正则表达式。
9.find命令。
1。管道和重定向
重定向输出
$ls -l > lsoutput.txt
这条命令把ls的输出重定向到lsoutput中。linux用非负整数来描述文件。称为文件描述符。
其中0表示标准输入,1表示标准输入,2表示标准错误输出。虽然很少,但依然可以重定向到这三个文件描述符中。
上面的例子 > 在默认的情况下,如果文件已经存在 ,那么他的内容将被覆盖。如果想改变默认行为,可以用set -o noclobber命令设置,从而阻止对已有文件的覆盖。(无法覆盖已存在的文件).可以使用set +o noclobber命令取消。
也可以使用>>操作符将输出内容附加到一个文件中。
例如: ps >> lsoutput.txt 这条命令将PS命令的输出添加到指定文件的尾部。
将标准输出和标准错误输出重定向到不同文件。
kill - HUP 1234 >killout.txt 2>killerr.txt 这里 2 代表标准输出
重定向输入
如:more < killout.txt。
但是这样做的意义并不大,因为more是允许带文件名参数的。
2.管道
又一个神奇的东西。linux可以用管道操作符|来连接进程。与windows不同的是,linux连接的这两个进程是同时进行的,然后进行协调。
例如,使用sort对ps命令的输出进行排序。
不用管道的话,需要以下步骤。
1.ps > psout.txt
2.sort psout.txt > pssort.out
使用管道,则可以这么写
ps | sort > pssort.out
如果想在屏幕上分页显示输出结果,可以连接第三个进程more,例如:ps |sort |more。允许连接的进程没有限制。但是有一点值得注意,如果有一系列的命令需要执行,相应的输出文件是在这一组命令被创建的同时立刻被创建和写入的,所以决不要在命令流中重复使用相同的名字,否则将得不到任何结果。操作系统上的读者和写者问题。
作为程序设计语言的shell。
1.shell允许通配符扩展(通常称为globbing)。可以用*来匹配一个字符串,用?来匹配一个字符。而[set]允许匹配方括号中的任意一个字符。[^set]则匹配任何没有在方括号中出现的字符。扩展的花括号{}只对部分shell有效。(包括bash)。允许你将任意的字符串放在一个集合里,以供shell进行扩展。
例如:ls my_{finger,toe}s. 这个命令将列出文件my_fingers,my_toes。
2.创建脚本。
其中#表示注释,第一行中的#!/bin/sh ,是一种特殊的注释,告诉系统用来执行脚本文件的程序。shell脚本应该有一个退出码,用来表示执行结束后的状态。
3.shell的语法。
变量:在shell中通常使用变量之前并不需要事先作出声明。只是通过使用他们来创建他们。在默认情况下,所有变量都被看作是字符串并以字符串来储存。即使他们被赋值为数值。在shell中,可以在变量前加一个$符号来访问他的内容。当为变量赋值时,直接赋值即可。
其中,对赋值进行加双引号,可以忽略该字符串中的空格。此外,等号两边不能有空格。
$ sa=hello
$ echo $sa
hello
$ sa="hello world"
$ echo $sa
hello world
$ sa=7+5
$ echo $sa
7+5
引号的用法。
一般情况下,脚本文件的参数用空白字符分隔,如果你想在一个参数中包含一个或多个空格,必须给参数加上引号。假设引用$foo这样的变量,如果一个$变量表达式放在引号内,程序执行到这一行时就会把变量替换为它的值,如果你把它放在单引号中,就不会发生替换现象。你还可以通过在$面前加一个\字符来取消它的特殊含义。
例如:输入
#!/bin/bash
myvar="Hi there"
echo $myvar
echo "$myvar"
echo '$myvar'
echo \$myvar
echo enter some text
read myvar
echo '$myvar' now equals $myvar
exit 0
输出]
Hi there
Hi there
$myvar
$myvar
enter some text
wz
$myvar now equals wz
主要的环境变量
$HOME 当前用户家目录
$PATH 以冒号分隔的用来搜索命令的目录列表
$PS1 命令提示符,通常是$
$PS2 二级命令提示符,用来提示后续的输入,通常是>字符
$IFS 输入域分隔符,空格,tab,或者回车之类。
$0 shell脚本的名称
$# 传递给脚本的参数个数
$$ shell脚本的进程号,脚本程序通常用它来生成一个唯一的临时文件,如/tmp/tmpfile_$$
参数变量
$1,$2...... 脚本程序的参数
$* 在一个变量中列出所有的参数,各个参数之间用环境变量IFS中的地一个字符隔开。如果IFS被修改了,那么$*也改变。
$@ 它是$*的一种便提,他不使用IFS环境变量,所以即使IFS为空,参数也不会挤在一起。
条件
test或 [ 命令
这两个命令的作用是一样的,只是为了增强可读性,在使用[命令时,使用]符号来结尾。
if test -f fred.c
then
..
fi
还可以写成
if [ -f fred.c ]
then
..
fi
这里必须注意的一点是[符号和被检查的条件之间必须留出空格。可以把[看作是test命令,而test命令每次都要留一个空格,一样的道理。[命令也要留一个空格。其中,如果then跟if写在同一行,必须加分号。表示if语句的结束。
字符串比较
str1 = str2 如果两个字符串相同则为真
str1 != str2 如果两个字符串不同则为真
-n str 如果字符串不为空则为真
-z str 如果字符串为空则为真
算术比较
e1 -eq e2 如果两个相等则为真
e1 -ne e2 如果不等则为真
e1 -gt e2 如果e1大于e2则为真
e1 -ge e2 如果e1大于等于e2则为真
e1 - lt e2 如果e1小于e2则为真
e1 -le e2 如果e1小于等于e2则为真
!ex 如果表达式为假则结果为真。
文件测试条件
-d file 如果文件是一个目录则结果为真
-e file 如果文件存在则结果为真。要注意的是,历史上-e选项不可移植,所以通常使用-f选项。
-f file 如果文件是一个普通文件则结果为真
-g file 如果文件的set-groub-id位被设置则为真
-r file 如果文件可读则为真
-s file 如果文件的大小不为0则为真
-u file 如果文件的set-user-id位被设置则为真
-w file 如果文件可写则结果为真
-x file 如果文件可执行则结果为真
接下来给一个例子
#!/bin/bash
if [ -f /bin/bash ]
then
echo "file /bin/bash exists"
fi
if [ -d /bin/bash ]
then
echo "/bin/bash is a directory"
else
echo "/bin/bash is NOT a directory"
fi
输出
file /bin/bash exists
/bin/bash is NOT a directory
控制结构
1.if语句
if condition
then
statements
else
statements
fi
2.elif (else - if 的意思)
3.使用固定的字符串for循环
for varialbe in values
do
statements
done
例如:
$ for foo in bar fud 43
> do
> echo $foo
> done
输出:
bar
fud
43
程序创建foo变量,并在bar,fud,43,中循环。每次赋不同的值。
4.while语句
while condition
do
statements
done
5.until语句
until condition
do
statements
done
while循环至少执行一次,而until可能不需要执行。
6.case 语句
case varialbe in
pattern [|pattern]。。。)statements;;
pattern [|pattern]。。。)statements;;
。。。
esac
示例:
#!/bin/bash
echo "Codeing is life?Please answer yes or no "
read answer
case "$answer" in
yes) echo "god bless you";;
no) echo "you are smart";;
*) echo "sorry,answer not recongnized";;
esac
exit 0
case语句被执行时,一旦某个字符串匹配成功,case 就会执行紧随)后面的代码,然后就结束。每个模式行都以两个 分号为结尾。在使用如 * 这样的通配符时要小心。因为case 将使用第一个匹配的模式,即使后续的模式有更加精确的匹配也是如此。其中每个case的条件可以合并,(与,或,非组合)。右括号)后面的语句也可以执行多条。
7.AND列表 以及 OR列表。
函数
示例:
#!/bin/bash
foo()
{
echo "function "
}
echo "script starting"
foo
echo "script ended"
exit 0
输出:
script starting
function
script ended
无返回值函数,有返回值的也类似。
从函数中返回一个值
首先,我们定义函数
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"
esac
done
}
下面是主程序部分
echo "Original parameters are $*"
if yes_or_no "$1"
then echo "Hi $1,nice name"
else
echo "never mind"
fi
exit 0
输出:
Original parameters are wz
Is your name wz ?
Enter yes or no:yes
Hi wz,nice name
命令
分为外部命令和内部命令(shell内置)。
1.break 命令
2.:命令,是一个空命令,偶尔被用于简化条件逻辑,相当与true的别名。由于是内置命令,比true运行的快。但可读性较差。
3.continue命令
4. 点(.)命令。用于在当前shell中执行命令。
5.echo命令。(通常用echo -n 去掉换行,建议用printf实现)
6.eval命令 允许对参数进行求值。
7.exec命令。典型用法是将当前shell替换为一个不同的程序。例如:exec wall “thanks ”脚本中的这个命令wall替换当前的shell。脚本程序中exec命令后面的代码都不会执行,因为执行这个脚本的shell已经不存在了。另一种用法是修改当前文件描述符(相当少见)
8.exit n 命令。退出码。shell变成中,0表示成功,1~125是脚本程序的错误代码。126表示文件不可执行,127表示命令未找到,128及以上,出现一个信号。
9.export 导出变量
10.expr 将它的参数作为表达式来求值。
11.printf命令,只有最新版本的shell有此命令。
12.return 命令
13.set命令 作用是为shell设置参数变量。
14.shift命令 把所有参数变量左移一个位置。
15.trap命令 trap command signal , 有两个参数,第一个参数用于制定在接受到信号后将要采取的行动。第二个是要处理的信号名。
16.unset命令 从环境中删除变量或函数
17.find 命令(在系统中搜索文)
18.grep命令(在文件中搜索字符串)
19.正则表达式(不记了,用到的时候百度,那么多奇怪符号)
here文档。在shell 脚本程序中向一条命令传递输入的一种特殊方法是使用here文档。好吧。记不住了。就这样吧。
迈向图形化:dialog工具。
好吧,我对图形化一直没什么好感。就这样吧。。。。
shell还是没能仔细看太多。不过就这样吧,能看的懂就好了。一个大的工程,需要具备各个方面的知识。不求甚解啊。接下来就是文件编程了。需要重点掌握。
在这里祝福中国的LOL战队,希望你们在世界决赛的舞台上表现得更好。恭喜皇族,晋级四强。OMG也很强,感到很可惜,假若这两个队不在同一组,今年的总决赛相当有可能是中国队之争。唉,Tabe的手真心太臭了。一抽就抽中OMG。我的天!。
皇族加油,中国队加油!!
之前也有过了解linux shell编程,这都是随便瞟过,想想也挺后悔。这么强大的工具,主要是这语法有点恶心。忍忍吧。毕竟要重新学,就学得认真点。
本章将学习:
1.什么是shell
2.基本思路
3.微妙的语法:变量,条件判断和程序控制。
4.命令列表。
5.函数
6.here文档
7.调试
8.grep命令和正则表达式。
9.find命令。
1。管道和重定向
重定向输出
$ls -l > lsoutput.txt
这条命令把ls的输出重定向到lsoutput中。linux用非负整数来描述文件。称为文件描述符。
其中0表示标准输入,1表示标准输入,2表示标准错误输出。虽然很少,但依然可以重定向到这三个文件描述符中。
上面的例子 > 在默认的情况下,如果文件已经存在 ,那么他的内容将被覆盖。如果想改变默认行为,可以用set -o noclobber命令设置,从而阻止对已有文件的覆盖。(无法覆盖已存在的文件).可以使用set +o noclobber命令取消。
也可以使用>>操作符将输出内容附加到一个文件中。
例如: ps >> lsoutput.txt 这条命令将PS命令的输出添加到指定文件的尾部。
将标准输出和标准错误输出重定向到不同文件。
kill - HUP 1234 >killout.txt 2>killerr.txt 这里 2 代表标准输出
重定向输入
如:more < killout.txt。
但是这样做的意义并不大,因为more是允许带文件名参数的。
2.管道
又一个神奇的东西。linux可以用管道操作符|来连接进程。与windows不同的是,linux连接的这两个进程是同时进行的,然后进行协调。
例如,使用sort对ps命令的输出进行排序。
不用管道的话,需要以下步骤。
1.ps > psout.txt
2.sort psout.txt > pssort.out
使用管道,则可以这么写
ps | sort > pssort.out
如果想在屏幕上分页显示输出结果,可以连接第三个进程more,例如:ps |sort |more。允许连接的进程没有限制。但是有一点值得注意,如果有一系列的命令需要执行,相应的输出文件是在这一组命令被创建的同时立刻被创建和写入的,所以决不要在命令流中重复使用相同的名字,否则将得不到任何结果。操作系统上的读者和写者问题。
作为程序设计语言的shell。
1.shell允许通配符扩展(通常称为globbing)。可以用*来匹配一个字符串,用?来匹配一个字符。而[set]允许匹配方括号中的任意一个字符。[^set]则匹配任何没有在方括号中出现的字符。扩展的花括号{}只对部分shell有效。(包括bash)。允许你将任意的字符串放在一个集合里,以供shell进行扩展。
例如:ls my_{finger,toe}s. 这个命令将列出文件my_fingers,my_toes。
2.创建脚本。
其中#表示注释,第一行中的#!/bin/sh ,是一种特殊的注释,告诉系统用来执行脚本文件的程序。shell脚本应该有一个退出码,用来表示执行结束后的状态。
3.shell的语法。
变量:在shell中通常使用变量之前并不需要事先作出声明。只是通过使用他们来创建他们。在默认情况下,所有变量都被看作是字符串并以字符串来储存。即使他们被赋值为数值。在shell中,可以在变量前加一个$符号来访问他的内容。当为变量赋值时,直接赋值即可。
其中,对赋值进行加双引号,可以忽略该字符串中的空格。此外,等号两边不能有空格。
$ sa=hello
$ echo $sa
hello
$ sa="hello world"
$ echo $sa
hello world
$ sa=7+5
$ echo $sa
7+5
引号的用法。
一般情况下,脚本文件的参数用空白字符分隔,如果你想在一个参数中包含一个或多个空格,必须给参数加上引号。假设引用$foo这样的变量,如果一个$变量表达式放在引号内,程序执行到这一行时就会把变量替换为它的值,如果你把它放在单引号中,就不会发生替换现象。你还可以通过在$面前加一个\字符来取消它的特殊含义。
例如:输入
#!/bin/bash
myvar="Hi there"
echo $myvar
echo "$myvar"
echo '$myvar'
echo \$myvar
echo enter some text
read myvar
echo '$myvar' now equals $myvar
exit 0
输出]
Hi there
Hi there
$myvar
$myvar
enter some text
wz
$myvar now equals wz
主要的环境变量
$HOME 当前用户家目录
$PATH 以冒号分隔的用来搜索命令的目录列表
$PS1 命令提示符,通常是$
$PS2 二级命令提示符,用来提示后续的输入,通常是>字符
$IFS 输入域分隔符,空格,tab,或者回车之类。
$0 shell脚本的名称
$# 传递给脚本的参数个数
$$ shell脚本的进程号,脚本程序通常用它来生成一个唯一的临时文件,如/tmp/tmpfile_$$
参数变量
$1,$2...... 脚本程序的参数
$* 在一个变量中列出所有的参数,各个参数之间用环境变量IFS中的地一个字符隔开。如果IFS被修改了,那么$*也改变。
$@ 它是$*的一种便提,他不使用IFS环境变量,所以即使IFS为空,参数也不会挤在一起。
条件
test或 [ 命令
这两个命令的作用是一样的,只是为了增强可读性,在使用[命令时,使用]符号来结尾。
if test -f fred.c
then
..
fi
还可以写成
if [ -f fred.c ]
then
..
fi
这里必须注意的一点是[符号和被检查的条件之间必须留出空格。可以把[看作是test命令,而test命令每次都要留一个空格,一样的道理。[命令也要留一个空格。其中,如果then跟if写在同一行,必须加分号。表示if语句的结束。
字符串比较
str1 = str2 如果两个字符串相同则为真
str1 != str2 如果两个字符串不同则为真
-n str 如果字符串不为空则为真
-z str 如果字符串为空则为真
算术比较
e1 -eq e2 如果两个相等则为真
e1 -ne e2 如果不等则为真
e1 -gt e2 如果e1大于e2则为真
e1 -ge e2 如果e1大于等于e2则为真
e1 - lt e2 如果e1小于e2则为真
e1 -le e2 如果e1小于等于e2则为真
!ex 如果表达式为假则结果为真。
文件测试条件
-d file 如果文件是一个目录则结果为真
-e file 如果文件存在则结果为真。要注意的是,历史上-e选项不可移植,所以通常使用-f选项。
-f file 如果文件是一个普通文件则结果为真
-g file 如果文件的set-groub-id位被设置则为真
-r file 如果文件可读则为真
-s file 如果文件的大小不为0则为真
-u file 如果文件的set-user-id位被设置则为真
-w file 如果文件可写则结果为真
-x file 如果文件可执行则结果为真
接下来给一个例子
#!/bin/bash
if [ -f /bin/bash ]
then
echo "file /bin/bash exists"
fi
if [ -d /bin/bash ]
then
echo "/bin/bash is a directory"
else
echo "/bin/bash is NOT a directory"
fi
输出
file /bin/bash exists
/bin/bash is NOT a directory
控制结构
1.if语句
if condition
then
statements
else
statements
fi
2.elif (else - if 的意思)
3.使用固定的字符串for循环
for varialbe in values
do
statements
done
例如:
$ for foo in bar fud 43
> do
> echo $foo
> done
输出:
bar
fud
43
程序创建foo变量,并在bar,fud,43,中循环。每次赋不同的值。
4.while语句
while condition
do
statements
done
5.until语句
until condition
do
statements
done
while循环至少执行一次,而until可能不需要执行。
6.case 语句
case varialbe in
pattern [|pattern]。。。)statements;;
pattern [|pattern]。。。)statements;;
。。。
esac
示例:
#!/bin/bash
echo "Codeing is life?Please answer yes or no "
read answer
case "$answer" in
yes) echo "god bless you";;
no) echo "you are smart";;
*) echo "sorry,answer not recongnized";;
esac
exit 0
case语句被执行时,一旦某个字符串匹配成功,case 就会执行紧随)后面的代码,然后就结束。每个模式行都以两个 分号为结尾。在使用如 * 这样的通配符时要小心。因为case 将使用第一个匹配的模式,即使后续的模式有更加精确的匹配也是如此。其中每个case的条件可以合并,(与,或,非组合)。右括号)后面的语句也可以执行多条。
7.AND列表 以及 OR列表。
函数
示例:
#!/bin/bash
foo()
{
echo "function "
}
echo "script starting"
foo
echo "script ended"
exit 0
输出:
script starting
function
script ended
无返回值函数,有返回值的也类似。
从函数中返回一个值
首先,我们定义函数
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"
esac
done
}
下面是主程序部分
echo "Original parameters are $*"
if yes_or_no "$1"
then echo "Hi $1,nice name"
else
echo "never mind"
fi
exit 0
输出:
Original parameters are wz
Is your name wz ?
Enter yes or no:yes
Hi wz,nice name
命令
分为外部命令和内部命令(shell内置)。
1.break 命令
2.:命令,是一个空命令,偶尔被用于简化条件逻辑,相当与true的别名。由于是内置命令,比true运行的快。但可读性较差。
3.continue命令
4. 点(.)命令。用于在当前shell中执行命令。
5.echo命令。(通常用echo -n 去掉换行,建议用printf实现)
6.eval命令 允许对参数进行求值。
7.exec命令。典型用法是将当前shell替换为一个不同的程序。例如:exec wall “thanks ”脚本中的这个命令wall替换当前的shell。脚本程序中exec命令后面的代码都不会执行,因为执行这个脚本的shell已经不存在了。另一种用法是修改当前文件描述符(相当少见)
8.exit n 命令。退出码。shell变成中,0表示成功,1~125是脚本程序的错误代码。126表示文件不可执行,127表示命令未找到,128及以上,出现一个信号。
9.export 导出变量
10.expr 将它的参数作为表达式来求值。
11.printf命令,只有最新版本的shell有此命令。
12.return 命令
13.set命令 作用是为shell设置参数变量。
14.shift命令 把所有参数变量左移一个位置。
15.trap命令 trap command signal , 有两个参数,第一个参数用于制定在接受到信号后将要采取的行动。第二个是要处理的信号名。
16.unset命令 从环境中删除变量或函数
17.find 命令(在系统中搜索文)
18.grep命令(在文件中搜索字符串)
19.正则表达式(不记了,用到的时候百度,那么多奇怪符号)
here文档。在shell 脚本程序中向一条命令传递输入的一种特殊方法是使用here文档。好吧。记不住了。就这样吧。
迈向图形化:dialog工具。
好吧,我对图形化一直没什么好感。就这样吧。。。。
shell还是没能仔细看太多。不过就这样吧,能看的懂就好了。一个大的工程,需要具备各个方面的知识。不求甚解啊。接下来就是文件编程了。需要重点掌握。
在这里祝福中国的LOL战队,希望你们在世界决赛的舞台上表现得更好。恭喜皇族,晋级四强。OMG也很强,感到很可惜,假若这两个队不在同一组,今年的总决赛相当有可能是中国队之争。唉,Tabe的手真心太臭了。一抽就抽中OMG。我的天!。
皇族加油,中国队加油!!