shell是操作系统与用户间的接口程序。
1.管道和重定向
重定向输出:
ls -l > lsoutput.txt#将ls的输出输出到lsoutput.txt文件中
ps >> lsoutput.txt#将ps的输出追加到lsoutput.txt文件后面
kill -HUP 1234 >killout.txt 2>killerr.txt #将进程的标准输出输出到killout.txt中,标准错误输出输出到killerr.txt中。
重定向输入
more < lsoutput.txt #将lsoutput.txt的内容输入到more中。more是一个可以用来查看文件内容的指令
管道
Linux中,管道可以用来连接进程,并且可以协调管道中的数据。管道连接的几个进程能够同时进行。
比如,如果不使用管道,指令要分几次执行:
jiang@ubuntu:~$ ls -l > lsoutput.txt
jiang@ubuntu:~$ sort lsoutput.txt > lsoutput.out
如果使用管道,则可以合并成一条指令
jiang@ubuntu:~$ ls | sort > lstext.out
管道对之后连接的指令数没有限制。
2.作为程序设计语言的shell
编写shell脚本程序的两种方式:在命令行输入并且交互地执行它们;将指令输入到一个文件中,将文件作为程序调用。脚本的好处在于可以重用。
创建脚本文件的步骤:
第一步:vi xxx.sh #创建脚本文件
第二步:#!/bin/bash
# XXX
echo "test test test"
第三步:保存,退出
第四步:执行 (执行方法; ./xxx.sh 或者 sh xxx.sh)
举例,有文件echo.sh
#!/bin/bash
echo "test file"
exit 0
然后改变权限(一定要改变权限,r,w,x,分别是读,写,执行权限)
jiang@ubuntu:~$ chmod u+x echo.sh
终端执行的时候输入
jiang@ubuntu:~$ sh echo.sh
test file
jiang@ubuntu:~$ ./echo.sh
test file
exit 0 的作用是确保脚本程序返回有意义的退出码。
可以使用以下指令改变文件的所有者或者权限
chown root /usr/bin/first#将first文件的所有者改变为root
chgrp root /usr/bin/first#将first文件的组改变为group
chmod 755 /usr/bin/first#改变firsst文件的权限
一般拥有写权限代表有权限删除该文件。所以一般写权限只有root用户拥有
3.shell语法
shell中的变量默认为字符串类型。当真正使用的时候系统会将它们转换成合适的类型。在变量前加$可以获取变量的内容。使用echo指令能够将变量显示出来,使用read指令将用户输入值赋值给某个变量。
jiang@ubuntu:~$ salutation=7+5
jiang@ubuntu:~$ echo salutation
salutation
jiang@ubuntu:~$ echo $salutation
7+5
jiang@ubuntu:~$ salutation=mode
jiang@ubuntu:~$ echo $salutation
mode
jiang@ubuntu:~$ read salutation
fly my 2 the moon
jiang@ubuntu:~$ echo $salutation
fly my 2 the moon
shell中,双引号内的变量在被调用的时候会被换成它的值,但是单引号内的不会替换。测试用例如下:
#!/bin/bash
var="hello world"
echo $var
echo "$var"
echo '$var'
echo \$var
echo var
echo "var"
echo 'var'
echo \var
read var
echo $var
echo '$var' equals to $var
exit 0
结果
jiang@ubuntu:~$ sh test.sh
hello world
hello world
$var
$var
var
var
var
var
hi there
hi there
$var equals to hi there
shell 使用test 或者[ ]进行布尔值的判断。注意[ ]的前后方括号必须与判断条件之间保持一个空格。判断一个文件是否存在的示例代码如下:
#!/bin/bash
if test -f fred.c
then
echo "fred.c exits"
fi
if [ -f echo.sh ]
then
echo "echo.sh exits"
fi
请注意:shell会忽略语句前的空白符(不像python缩进很重要)
exit返回的数字不为0代表程序运行出错
1). if 语句块
可以使用elif来修饰 if 语句块
if 语句块的语法是这样的:
if
then
elif
then
else
fi
2)for 语句块
基本语法为:
for
do
done
3) while语句块
while condition
do
done
4)case语句块
你必须很小心地尽量把最精确的匹配放在最前面
case xxxx in
patern1) statement1;;
patern2) statement2;;
...
esac
5)命令列表
- AND逻辑和OR逻辑 : &&和||能够连接表达式,简化if else逻辑。
- break命令
- continue 命令
- echo命令
- eval命令
- .命令
- exec命令
- exit n命令:exit 0 程序正常执行结束之后退出;exit 非零 ,程序未正确执行。exit 126 程序不可执行;exit 127 ;命令未找到;exit 128及以上:出现一个信号。
- export命令 将该shell中的变量导入子shell中。也就是加了export关键字的变量在子shell中可见。
- expr命令:表达式求值
- printf命令:关键字格式打印
- set命令:将函数输出作为参数变量,按照$1 $2的方式可以取出变量值。
- unset命令:删除某个变量
- shift命令:将变量顺序向左移动,也就是说$2替换$1,$3替换$2以此类推。$1变量被扔掉。
- find命令:全局搜索某个文件
- grep命令:general regular expression parser正则化表达式解析器。经常和find一起使用。
- 指令举例,假设两个文件re1.txt和re2.txt
-
grep in re1.txt#在re1.txt中找到与字符串in匹配的地方 grep -c in re1.txt re2.txt#在re1.txt和re2.txt中搜索匹配(或者说是含有)in字符串的行数(而不是行) grep -c -v in re1.txt re2.txt#在re1.txt和re2.txt中搜索不含有in的行数
6)命令的执行
- 算术运算:把准备求的表达式放在$((...))中,能够完成数值运算。比如:
#!/bin/sh x=0 while [ "$x" -ne 10 ];do echo $x x=$(($x+1)) done exit 0
如果x不等于10,就执行下面的步骤。
- 参数扩展以及实例
#!/bin/sh
unset foo#删除参数foo
echo ${foo:-bar} #如果foo为空值,则将其值设置为bar,本条语句返回的是bar
foo=fud#设置的foo的值为fud
echo ${foo:-bar}#如果foo为空值,则返回bar,但是这里foo设置过值了,因此返回fud
foo=/usr/bin/X11/startx
echo ${foo#*/} #删除与正则表达式*/匹配的最小的字符串,并返回剩下的部分。因此仅删除/
#输出的是usr/bin/X11/startx
echo ${foo##*/}#删除与*/匹配的最大的字符串,并返回剩下的,因此删除掉是除了startx以外的
#返回startx
bar=/usr/local/etc/local/networks
echo ${bar%local*} #删除local*匹配的最小的字符串,返回剩下的字符串,因此返回的是/usr/local/etc/
echo ${bar%%local*} #删除local*匹配的最大的字符串,返回剩下的字符串,因此返回的是/usr/
exit 0
7)here文档
允许命令从脚本文件中获取输入的一种方式。基本格式是:命令<<!FUNCK(或者其他的一个字符串)!...(你要输入的内容)!FUNCK(与开头相同的字符串)!
#!/bin/sh
cat<<!FUNKY!
hello
there is a here
document
!FUNKY!