1.小试牛刀

1.1 简介

  • $表示普通用户,#表示root用户,root的UID是0
  • bash里命令可以用分号分隔

 

1.2 终端打印

  • 不管是echo还是printf,双引号里打印特殊字符都需要转义
  • echo中如果要使用转义序列,使用echo -e
    $ echo -e "This\tis\tme.\nOK"
    This	is	me.
    OK

 

1.3 玩转变量和环境变量

  • 使用 env 查看和终端相关的变量
  • 使用以下两个命令之一
    $ ps aux
    $ ps -ely
    查看进程信息,或者
    $ pgrep sslocal 
    19582
    查询进程ID,然后
    $ sudo cat /proc/19582/environ
    LANG=zh_CN.UTF-8
    查看某个进程的环境变量。
  • 打印变量时使用单引号会原封不动输出,使用双引号才会拓展开,此时若变量未定义则不打印这个变量:
    $ printf "I am ${var}"
    I am %
    $ var="boy"
    $ printf "I am ${var}"
    I am boy%
  • 变量前加#号会取这个变量(字符串)的长度
    $ echo $#var
    3
  • echo $0等同于echo $SHELL

 

1.6玩转文件描述符及重定向 

  • 文件描述符是与某个打开的文件或数据流相关联的整数。0表示stdin即标准输入,1表示stdout即标准输出,2表示stderr即标准错误。
  • 使用 重定向到文本,在这之前这个文本的内容会被清空,而 >> 是在文本末尾追加。将stderr重定向到文本可以使用 cmd 2>err.txt 。如果想把stdout输出的同时也输出stderr可以 cmd 2>err.txt 1>out.txt ,想都输出到一个文件里可以 cmd 2>&1 out.txt 或者直接 cmd &> out.txt 。若想丢弃stderr则 cmd 2>/dev/null
  • 接收stdout保存到文件的同时想提供副本给后续命令的stdin,可以 cmd | tee out.txt | cat -n ,但是只能打印标准输出而不能打印标准错误,因为tee只接收stdout。tee通常会覆盖文件除非使用 -a 参数在文本追加。
  • cat <<EOF> out.txt 表示从输入流获取直到获取到EOF,然后写入文件,这和以下shell脚本作用是一样的:
    $ cat a.sh
    #! /bin/bash
    cat >out.txt <<EOF
    I am OK.
    EOF
    $ ./a.sh
    $ cat out.txt
    I am OK.
  • 自定义文件描述符 exec >exec <exec >> 对应着截断写入模式、只读模式、追加写入模式。像这样用:
    $ exec 3>out.txt
    $ echo This is it.>&3
    $ cat out.txt
    This is it.

 

1.7数组和关联数组 

注意:zsh和bash的不同点之一就是数组的下标从1开始

  • 定义关联数组(也有人称作哈希表):
    $ declare -A array
    $ array=([apple]=100 [orange]=90)
    $ echo "An apple's price is \$$array[apple]"
    An apple's price is $100
    declare typeset 是一样的。在zsh中列出数组索引的方式和在bash中不同:
    #bash下:
    $ declare -A array_a
    $ array_a=([apple]=100  [orange]=90)
    $ echo ${!array_a[@]}
    apple orange
    $ echo ${!array_a[*]}
    apple orange
    
    #zsh下:
    $ echo ${(k)array}
    apple orange

1.8使用别名alias

  • 别名的用法,在书中这里的用法有问题,好像因为年代久远吧(▔□▔):
    #书上的:
    $ alias my_rm='echo "cp $@ ~/new && rm $@"'
    $ my_rm  ./out.txt                         
    cp  ~/new && rm  ./out.txt
    #可以看到参数的替换有问题
    #改版:
    $ cat rm.sh 
    #!/bin/zsh
    new_rm(){
    cp $@ ~/new
    rm $@ 
    }
    new_rm $@
    
    $ ls ./new 
    
    $ cat ./out.txt 
    This is it.
    
    $ ./rm.sh ./out.txt 
    
    $ cat ./out.txt
    cat: ./out.txt: 没有那个文件或目录
    $ find ./new -type f -print0 | xargs --null cat
    This is it.
  • 使用 \command 的方式可以对命令转义,使用原始的命令而不查询别名,在不安全的环境中可以防止一些意料之外的事情发生。