Shell脚本入门
Shell 脚本
Shell 是一种UNIX/Linux应用程序,这个应用程序提供了一个接口,用户通过这个接口访问操作系统内核的服务
shell有很多种实现,包括sh(Bourne SHell), bash(Bourne Again SHell), dash(Debian Almquist shell)等
shell脚本是用于shell程序的脚本,解释型的脚本编程语言,易于处理文件目录之类的对象,编写简单,速度快,符合POSIX标准,可移植
举个例子
#! /bin/sh -
who | wc -l
其中,第一行的 #! 用于指定shell的位置,例如,一个linux系统既有dash, 又有bash,要使用bash需要写#! /bin/bash
who | wc -l 是个用于计数用户,who查看当前在线的用户,|作为管道把who得到的文本给下一个程序wc,wc -l用于统计行数,也就是有多少用户在线
基础要点
shell的基本工作是执行命令, 不仅仅可以写成如上的文本文件,还可以交互式执行
-
语法
命令+选项+参数
末尾的;分隔同一行的多个命令, 末尾的&会使命令在后台执行
$ cd work; ls -l whizprog.c
$ make
-
三种基本命令
内建命令:shell本身所执行的命令,如cd改变目录
shell函数: 用shell语言写成的代码,可以像命令一样引用
外部命令:由shell的副本执行的命令,父shell等待子shell完成命令
-
变量与赋值
shell变量名开头是一个字母或者下划线
变量赋值使用等号,等号两侧不能有空格,例如
first=isaac
middle=bashevis
last=singer
fullname="isaac bashevis singer"
oldename=$fullname
连接变量为新变量赋值需要加引号
echo "$first $middle $last"
-
命令行参数传入
使用$+数字访问命令行参数,数字大于10要加括号,例如
echo first argument is $1
echo tenth argument is ${10}
-
查找命令的路径$PATH
shell会沿着$PATH中记录的路径查找命令
$PATH是用:隔开的一些目录,空项目代表当前目录,其位置决定其被查找的先后,更好的表示当前目录的方式是用点号
/home/caiji/bin:/home/caiji/perl5/bin:/home/caiji/.local/bin:/home/caiji/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin
可以把自己写的脚本所在的目录,加入到$PATH
$ PATH=$PATH:$HOME/bin
如果要永久生效,需要把上面的语句写在.profile文件中
-
基本IO/重定向/管道
shell的默认输入输出是终端, 例如
$ cat
now is the time
now is the time
for all good men
for all good men
ctrl+D
- 重定向
要注意的是,>输出会覆盖原有文件内容,>>输出会追加到文件结尾
# 从file.txt输入
$ program < file.txt
# 输出到file.txt
$ program > file.txt
# program >> file.txt
- 管道
一个程序的输出可以通过管道传给另一个程序,比重定向快很多
program1 | program2
- 特殊文件
/dev/null: 位桶,重定向到这里的内容都被丢弃,不被输出
if grep pattern myfile > /dev/null
then
...
else
...
fi
/dev/tty: 重定向到另一个终端,如下stty -echo可以隐藏输入
printf "Enter new password: "
stty -echo
read pass < /dev/tty
printf "\n"
printf "Enter again: "
read pass2 < /dev/tty
printf "\n"
stty echo
-
命令追踪
使用set -x可以打开追踪,在命令执行之前打印命令
#! /bin/sh
set -x
echo 1st echo
set +x
echo 2nd echo
执行如下
$ ./trace1.sh
+ echo 1st echo
1st echo
+ set +x
2nd echo
几个常用的命令
-
cat
直接输出到终端很简单,下面的命令可以复制到剪贴板
$ cat file.txt | xsel
也可以重定向标准输入到文件
$ cat > file.txt
abcdefg
ctrl+D
$ cat file.txt
abcdefg
-
echo
echo
语法: echo [ string ... ]
用途: 产生shell脚本输出
主要选项: 无
模式: 把参数之间用空格隔开,打印到输出,自动添加换行
例如:
$ echo $PATH
/home/caiji/bin:/home/caiji/perl5/bin:/home/caiji/.local/bin:/home/caiji/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin
$
一个有趣的转义字符是\r 和\n
\r : 光标到行首
\n : 换行
linux/unix换行: \n
windows 换行: \n\r
mac换行: \r
windows下的文件可以在linux下处理\r后打开,tr命令在后面有讲解
tr -d '\r' < doc-file.txt > unix-file.txt
-
printf
豪华版echo,但是不自动换行
类似于C语言的printf
printf [ 格式声明... ] [ 参数列表... ]
例如
string="abc"
number=5
printf "%s %d\n" $string $number
-
tr
tr是个有趣的命令,用于转换字符
# 例如,文件doc-file.txt
$ cat dos-file.txt
abcdefgg
hijklmn
# 删除a
$ tr -d 'c' < dos-file.txt
abdefgg
hijklmn
# 替换
$ tr 'c' 'd' < dos-file.txt
abddefgg
hijklmn
# 浓缩
$ tr -s 'g' < dos-file.txt
abcdefg
hijklmn