输入、输出相关
参数和变量
运行脚本时所输入的参数叫做位置参数(positional parameters),在脚本中可以用$1来获得第一个参数,$2获得第二个参数,以此类推。
比如说,有这样一个脚本hello:
#: Description: print Hello and the first command-line argument
printf "Hello, %s!\n" "$1"
那么,当你在命令行下输入
hello John
将会输出
Hello, John!
注意:在bash中,$10将会被解释为$1后接一个0,如果要获得第9个参数以后的参数,参数号要用大括号括起来,如${10}。
在脚本中有时可能会要用到一些特殊参数(special parameters),如:
$*:所有的位置参数(一个单词)
$@:所有的位置参数(每个参数一个单词)
$#:位置参数的个数
$$:当前进程的PID
$?:上一条命令的执行返回值(0为正常执行)$_为该命令的最后一个参数
$!:上一条在后台执行的命令对应的进程PID
$-:
变量的命名规则与大部分程序语言一样,只能包含字母、数字和下划线,且只能以字母和下划线开始。变量赋值形式为
name=VALUE(注意等号两边都没有空格)
有些变量是被shell自动赋值的,如HOME、PATH、PWD等,除了auto_resume 和 histchars,这些变量都是由大写构成的。
实参与选项
在任意一条命令中,实参都是用一个或多个空格(或tab)隔开的,如果空格也要包括到参数中,则可以用转义符‘\‘或用单引号将整个参数引起来,如:
echo 1 '2 3' 4 5中‘2 3’就是一个参数
echo 1 2\ 3 4 5和上面一样,也是只包含四个参数
选项如果是单个字母的话,则以‘-’开头,如
echo -n 1 2 3 4 5
否则以‘--’开头,如--version
由于echo在AT&T系统和BSD系统下某些执行会有不同的输出结果,所以对于一些复杂的、需要格式的输出,最好使用printf
printf
与C类似,格式为:
printf FORMAT ARG ...
printf "Q\t\141\n\x42\n"
输出将会是
Q
a
B
这是因为\t为tab,\141表示一个字符,其ASCII码在八进制下为141,\x42也表示一个字符,其ASCII码在十六进制下为42,\n为换行。
如果printf的ARG部分的实参超过了FORMAT中的形参,则FORMAT将会被重复使用,直到输出所有的ARG。
%b与%s类似,不同的是%s不会翻译ARG中出现的转义符,而%b会。
%d会将以0开头的数字认为是八进制,以0x开头的数字认为是十六进制,如果不是合法数字(如有小数点),则会输出错误信息。
%f会将浮点数保留到小数点后六位。
‘%’后接整数表示宽度,正数表示右对齐,负数表示左对齐。
‘%'后接小数则整数部分表示宽度,小数部分表示精度。
例:report
#!/bin/bash
#: Description : print formatted sales report
## Build a long string of equals signs
divider=====================================
divider=$divider$divider
## Format strings for printf
header="\n %-10s %11s %8s %10s\n"
format=" %-10s %11.2f %8d %10.2f\n"
## Width of divider
totalwidth=44
## Print categories
printf "$header" ITEM "PER UNIT" NUM TOTAL
## Print divider to match width of report
printf "%$totalwidth.${totalwidth}s\n" "$divider"
## Print lines of report
printf "$format" \
Chair 79.95 4 319.8 \
Table 209.99 1 209.99 \
Armchair 315.49 2 630.98
在bash 3.1中,printf添加了-v选项,类似于赋值,如
printf -v num4 "%04d" 4
就是将num4的值设为0004。
标准输入输出和重定向
标准输入、输出、错误都是默认下与终端相关联的,它们的文件描述符分别为0,1,2。可以通过‘>>’、‘>’和‘<’来对这些流进行重定向。
如果要忽略某个流,可以将其重定向到/dev/null,如:
printf '%s\n%v\n' OK? Oops! 2>/dev/null 忽略了标准错误流。
注意
printf '%s\n%v\n' OK? Oops! > FILE 2>&1 与
printf '%s\n%v\n' OK? Oops! 2>&1 > FILE 的区别。
可以用&>>FILE将标准输出和错误都重定向到FILE文件中。
读入
read a b c d
如果输入
1 2 3 4 5 6 7 8,则
a为1,b为2,c为3,d为4 5 6 7 8
read也可以重定向,如:
read var < FILENAME
管道
因为每条命令的执行结果都是流,所以可以通过管道,将一条命令的输出作为另一条命令的输入。
printf "%s\n" "$RANDOM" "$RANDOM" "$RANDOM" "$RANDOM" | tee FILENAME
会参生四个随机数输入到文件FILENAME中去。
如果要将命令的执行结果赋给一个变量,可以:
var=`command`,注意`不是单引号,是~下的那个符号,也可以
var=$(command),但这两者执行速度会比较慢,这也是为什么要对printf添加-v选项,通过它对变量赋值速度会比上述两种方法快。
总结
用到的相关命令行:
cat:将一个或多个文件的内容输出到标准输出。
tee:将标准输入输出到标准输出和一个或多个文件。
read:在shell中读取标准输出。
date:输出当前时间。