- Notifications
You must be signed in to change notification settings - Fork 5
Description
shell
变量与变量展开
hello=world echo $hello hello="i am world" echo $hello echo hello world echo -n "enter your name:" (-n去掉行尾的回车) read name echo $name - $是取变量的值,所以总是出现在=号的右边
- =号前后不能有任何空格
- =号后面的字符串如果不包含空格可以不加""
- echo后面字符串即使包含空格也可不加"",
如果要正常输出变量中的换行符,则必须加双引号 - shell视所有变量为字符串类型.
- 单引号不展开变量, 仅原样输出字符串, 双引号会展开变量.
- 强制展开变量的办法:嵌套使用单引号,或者整体使用双引号或者拼字符串
$ sed -n '1 c$HOME' package.json(不会展开变量)
$HOME
$ sed -n "1 c$HOME" package.json(整体使用双引号)
/home/cyper
$ sed -n '1 c'$HOME'' package.json(嵌套使用单引号)
/home/cyper
$ sed -n '1 c'$HOME package.json(拼字符串)
/home/cyper
输出重定向
3个特殊的文件描述符0 stdin, 1 stdout, 2 stderr.
格式:command FILE_DESCRIPTOR>outputFileName
foo 1>ok.txt 2>error.txt 因为foo命令不存在,所以出错信息输出到了error.txt中,注意到同时生成了一个空的ok.txt文件, 其中标准输出重定向1>可以简写成>
怎么将正常的及错误的消息输出到同一文件foo 1>ok.txt 2>&1, 即使用&1来表示文件描述符为1对应的输出文件,在这里它们同时指向ok.txt.
引号
'原样输出 "会先做expansion 参数
$HOME 打印出/home/cyper $0: shell script的名字 $#: 参数个数 $$: 运行脚本时的process ID $1,$2, ...传递给脚本的参数 $*: 所有参数使用$IFS分隔(默认为空格) $@: 同$*但总是使用空格分隔 $?: 命令的退出状态,0成功,非0失败 PS1,PS2: 命令提示符 快速测试
$ IFS=’‘ $ set foo bar bam $ echo “$@“ foo bar bam $ echo “$*“ foobarbam $ unset IFS $ echo “$*“ foo bar bam条件测试
if test -f fred then ... elif test -d fred; then ... else ... fi 或
if [ -f fred.c ] then ... fi 或
if [ -f fred.c ]; then ... fi []和其中包含的测试条件必须用空格隔开
条件比较
| string comparison | result |
|---|---|
| str1 = str2 | string equal |
| str1 != str2 | string not equal |
| -n str | string is not null |
| -z str | string is null(an empty string) |
| num1 -eq num2 | exprs are equal |
| eq, ne, gt, ge, lt, le | ... |
| ! expr1 | is false? |
| -d file | is directory? |
| -e file | exist? |
| -f file | is file? |
| -r file | is readable? |
| -w file | is writable? |
| -x file | is executable? |
| -g file | if set-group-id is set on file? |
| -u file | if set-user-id is set on file? |
You may be wondering what the set-group-id and set-user-id (also known as set-gid and set-uid) bits are. The set-uid bit gives a program the permissions of its owner, rather than its user, while the set-gid bit gives a program the permissions of its group.The bits are set with chmod,using the s and g options.The set-gid and set-uid flags have no effect on files containing shell scripts, only on executable binary files.
特殊情况
if [ $timeofday = "yes" ]这段可能有问题, 当timeofday为空的时候if [ = "yes"]语法不合规,最好写成if [ "$timeofday" = "yes" ]
for
foriin foo bar 43 doecho$idone或
foriin$(ls f*.sh);do lpr $filedonewhile
echo"Enter password"read trythis while [ "$trythis"!="secret" ];doecho"sorry, try again"read trythis doneutil
who查看当前系统有哪个登录用户, 比如who|grep cyper返回0, 而who|grep green返回1, 这里我们只关心script的执行情况(0 or 1), 不关心stdout.
# 如果参数1对应的用户没有出现, 就等待60s后再次检测until who | grep "$1"> /dev/null do sleep 60 done# 响铃echo -e '\a'echo"**** $1 has just logged in ****"exit 0case
基本结构
case"$x"in pattern | pattern2 ) statements; * ) echo"default case"; esac例子:
#!/bin/shecho"Enter your name?"read timeofday case"$timeofday"in yes | y | Yes | YES ) echo"Good morning"echo"It's cool" ; [nN]*) echo"Good afternoon" ; *) echo"sorry"exit 1 ; esacexit 0AND
打印出hello in else
touch file_one rm -rf file_two if [ -f file_one ] &&echo"hello"&& [ -f file_two ] &&echo" there"thenecho"in if"elseecho"in else"fiOR
打印出hello in if
rm -f file_one if [ -f file_one ] ||echo"hello"||echo"there"thenecho"in if"elseecho"in else"fiStatement Blocks
可以用AND/OR选择性的执行语句块
get_confirm &&{echo "hello" echo "dome some other thing" } braces and brackets
braces()中的command在subshell中执行,在期间修改的env var不会影响current shell(比如执行了cd命令).在brackets{}中包含的command在当前shell中执行.
set -e
遇到错误即退出, 不继续执行后续脚本
set -o noclobber
打开此选项是为了防止使用重定向符>意外覆盖文件,如果要强制覆盖,使用>|.
Here document
用来快速提供多行输入,常用于交互式命令比如telnet, ftp.
command << terminaor [input ...] 或者 command <<- terminator [input ...] 每次读一行,直到读到某行是terminator时结束,<<-会把input中每行前面的tabs去掉。
登录到一个远程机器并把某文件mail给本机。
$ telnet << END > open 190.100.2.1 > gregl password > mail -s "remote userlogs" [email protected] < /var/log/userlog > quit > END substitution
文件名替换: 使用w*,?,[a-z],
命令替换:
* 0或多个字符 ? 单个字符 [a-z0-9] 范围内单个字符 [!0-9] 范围外单个字符,和正则^不一样 $(command) 执行command并把输出结果作为其它命令的参数 $(< filename) 将filename的内容作为其它命令的参数 echo '*' 如果需要转递特殊字符做为参数,需要使用引号或\以防止该符号被shell解释. echo \* 同上 echo "*" 同上 Date
DATE=`date +%Y-%m-%d`$(date +%F) DATE=`date +%Y-%m-%d:%H:%M:%S`其中%Y-%m-%d <==> %F, 输出2017-04-26