2.4 管道和重定向
2.4.1 重定向
文件描述符 重定向 描述
0 < 标准输入
1 > 标准输入
2 > 标准错误输出
>> 追加
2>&1 标准输出和错误输出到同一个文件中
特别的,可以用/dev/null来有效的丢弃所有的输出信息
..... >/dev/null 2>&1
显示命令 > 文件
more/less < 文件
2.4.2 管道:连接进程,使得连接的进程可以同时运行
ps -xo comm|sort|uniq|grep -v sh|more
“|”后面的输入是其前面的输出
使得数据流在他们之间可以自动的进行协调。
$ cat mydate.c
dfdfkj
afljir
clkjfoi
而
$cat mydate.c |sort
afljir
clkjfoi
dfdfkj
可见sort不仅可以给目录呀,文件呀排序,还可以在在一个文件内给行排序,但是不能够在行内排序
而
$ cat mydate.c |sort|>mydate.c
显示的是空白,原因是你在读取mydate.c之前就已经覆盖了这个文件的内容,因此不能在管道中出现
输出的文件是在这一组命令被船舰的同时立刻被创建活写入。
2.5 shell
shell 脚本有两种方式:输入一系列命令让shell交互执行,如上;将命令保存到一个文件中,将该文件作为一个程序来调用
通配符
* 任意字符串
? 单个字符串
[abc...] 匹配方括号内任意一个单字符
[^abc..] 匹配除了方括号内任意一个单字符
{ab,dcd,...} 允许任意的字符串分组在一个集合中
如 my{ma,fa}se 值得就是 mymase myfase
2.5.1 交互式程序
直接在shell中输入命令,不过没法保存,没有重用性
2.5.2脚本
1 创建
# :注释符
#!/bin/sh :告诉系统后面的参数/bin/sh是用来执行本文件的程序
exit:确保程序返回一个有意义的退出码,当从另一个脚本程序里调用这个脚本并查看是否执行成功,退出码就很重要。
$ file first :用于检查文件类型
first: POSIX shell script text executable
2.5.3 执行
a. /bin/sh 脚本名
b. chmod +x 脚本名
脚本名
或者是 ./脚本名 把脚本程序的完整的相对路径且能够保证不会意外执行系统中于你的脚本文件通明的另一个命令。
如果此时告诉你没有找到该命令,是因为shell的PATH中没有被设置为当前目录下查找执行的命令。
方法一:在命令行上 PATH=¥PATH:.
方法二:将 脚本名 添加到 .bash_profile中,退出后重新登录
3.6 SHELL 语法
2.6.1 变量
使用变量前不需要声明。默认以字符串看待和存储的。
在变量名前加 $ 访问起内容。但为其赋值时,只需要变量名
1 使用引号
ke=ma ld
ld: no input files
对于有空格的必须用引号
$ke="ma ld"
$ echo $ke
ma ld
$ read ke 等待输入
dkf klfdj kle 输入
$ echo $ke
dkf klfdj kle 原文输出
#!/bin/sh
myvar="Hi there"
echo $myvar // Hi there
echo "$myvar" // Hi there
echo "myvar" // myvar
echo '$myvar' // $myvar
echo 'myvar' // myvar
echo /$myvar // $myvar
echo /myvar // myvar
echo Enter some text // Enter some text
read myvar // 等待输入
// 输入 HOW DO YOU DO
echo '$myvar' now equals $myvar // $myvar now equals HOW DO YOU DO
exit 0
从上面的实验可以知道:
1 对于变量的引用 使用 “”和不使用是一样的
2 在“”中没有 $ 的变量 只是字符串而已
3 ‘’的作用就是输出其中的字符串
4 / 的作用和 ‘’相同
2 环境变量
$HOME 当前用户的主目录
$PATH 以冒号分割的用来搜索命令的目录列表
$PS1 命令提示符
$IFS 输入域分割符,空格、TAB,ENTER
$0 shell脚本的名字
$# 传递给脚本的参数个数
$$ shell脚本的进程号
3 参数变量
$1,$2,... 脚本程序的参数
$* 在一个变量中列出所有的参数,参数间用IFS中的第一个字符分割开
$@ 与 $*意同,不使用IFS
$ IFS=''
$ set foo bar bam
$ echo $@
foo bar bam
$ echo "$@"
foo bar bam
$ echo $*
foo bar bam
$ echo "$*"
foobarbam
$ unset IFS
$ echo $IFS
$ echo "$*"
foo bar bam
如果想访问脚本程序的参数,用 $@ 最好
sa="Hello" //
echo $sa //Hello
echo "The program $0 is now running" // biangliang shell脚本的名字
echo "The second parameter was $2" // bar
echo "The first parameter was $1" // foo
echo "The parameter list was $*" //foo bar baz
echo "The script is now complete"
$ /bin/sh bianliang foo bar baz
2.6.2 条件
shell脚本对任何从命令行上被调用的命令的退出码进行测试。
test / [ 布尔判断命令 且" ["用“]”来结尾
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
执行结果为:
$ /bin/sh panduan
file /bin/bash exists
/bin/bash is NOT a directory
2.6.3 控制结构
echo "Please answer yes or no : Is it morning?" //shell用echo -e,bash用echo -n来去除换行符
read timeofday
if [ $timeofday = "yes" ] //一定要保持距离 if[ $timeofday 不行 ; if [ $timeofday="yes"也不行
then
echo "Good morning"
elif [ $timeofday = "no" ] //[ 对timeofday的内容进行测试,测试结果由if判断
then
echo "Good afternoon"
else
echo "Sorry,$timeofday is not recognized.Enter yes or no!"
exit 1
fi
exit 0
看似完美的程序,其实隐患重重,在不输入任何数据,直接ENTER后
[: 15: yes: unexpected operator
[: 15: no: unexpected operator
Sorry, is not recognized.Enter yes or no!
问题出在 当直接ENTER后,$timeofday 成为 空字符串
因此将 $timeofday 改为"$timeofday"
4 for 语句
for 循环经常与shell的文件名扩展一起使用
for variable in values_table
do
...$variable
done
for 循环经常与shell的文件名扩展一起使用
for file in *.sh
还有就是
for foo in 10
echo "here wo go"
这样能执行一次
for foo in 1 2 3 4 5 6 7 8 9 10
echo "here wo go"
却可以执行10次
而
for foo in 1 2 3 5 8 9 41 10 1 0
echo "here wo go"
依然是执行10次
参考:Linux 程序设计(v3)