1、终端打印
echo
[root@stone ~]# echo hello world !
hello world !
[root@stone ~]# echo 'hello world !'
hello world !
[root@stone ~]# echo "hello world !"
echo "hello world "
hello world 
[root@stone ~]# echo -n hello world !
hello world ![root@stone ~]# 
#echo 默认最后有一个换行符,加上‘-n’选项后,去掉换行符
[root@stone ~]# echo -e "hello\nworld" 
hello
world
[root@stone ~]# echo -e 'hello\nworld'
hello
world
[root@stone ~]# echo -e hello\nworld
hellonworld
#‘-e’选项可对以下字符进行特殊处理:
   \a 发出警告声;
   \b 删除前一个字符;
   \c 最后不加上换行符号;
   \f 换行但光标仍旧停留在原来的位置;
   \n 换行且光标移至行首;
   \r 光标移至行首,但不换行;
   \t 插入tab;
   \v 与\f相同;
   \\ 插入\字符;
   \nnn 插入nnn(八进制)所代表的ASCII字符;
#使用echo时参数最好使用引号。

printf
[root@stone bin]# cat printf.sh
#!/bin/bash
#printf.sh
printf "%-5s %-10s %-4s\n" No. Name Mark
printf "%-5s %-10s %-4.2f\n" 1 Sarath 80.3456
printf "%-5s %-10s %-4.2f\n" 2 James 80.3456
printf "%-5s %-10s %-4.2f\n" 3 Jeff 80.3456
[root@stone bin]# printf.sh
No.   Name       Mark
1     Sarath     80.35
2     James      80.35
3     Jeff       80.35

2、变量与环境变量
查看进程的环境变量
[root@stone bin]# pgrep bash
7297
[root@stone bin]# cat /proc/7297/environ 
USER=rootLOGNAME=rootHOME=/rootPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binMAIL=/var/mail/rootSHELL=/bin/bashSSH_CLIENT=172.16.3.151 3686 22SSH_CONNECTION=172.16.3.151 3686 172.16.3.54 22SSH_TTY=/dev/pts/1TERM=linux
[root@stone bin]# cat /proc/7297/environ | tr '\0' '\n'
USER=root
LOGNAME=root
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAIL=/var/mail/root
SHELL=/bin/bash
SSH_CLIENT=172.16.3.151 3686 22
SSH_CONNECTION=172.16.3.151 3686 172.16.3.54 22
SSH_TTY=/dev/pts/1
TERM=linux
[root@stone ~]# echo -e "\0" | od -a
0000000 nul  nl
0000002


变量赋值:var=value
变量引用:$var;${var}
单引号内的变量不会被解释,双引号内的变量才会被解释
设置环境变量:export var
[root@stone ~]# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@stone ~]# PATH="$PATH:/home/stone/bin"
[root@stone ~]# export PATH
[root@stone ~]# echo $PATH                  
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/home/stone/bin

获取字符串长度:${#str}
[root@stone ~]# str1=123456789
[root@stone ~]# echo ${#str1}
9

识别当前的shell版本
[root@stone ~]# echo $SHELL
/bin/bash
[root@stone ~]# echo $0
-bash

检查用户是否为超级用户
[root@stone ~]# echo $UID
0

3、算术运算
整数运算:let;(());[]
[root@stone ~]# num1=4;num2=5
[root@stone ~]# let result=num1+num2
#使用let时,变量前无需使用$
[root@stone ~]# echo $result
9
[root@stone ~]# let num1++;let num2--
[root@stone ~]# echo $num1 $num2
5 4
[root@stone ~]# let num1+=5;let num2+=6
[root@stone ~]# echo $num1 $num2
10 10
[root@stone ~]# result=$[ num1 + num2 ]
[root@stone ~]# echo $result
20
[root@stone ~]# result=$[ $num1 + $num2 ]
[root@stone ~]# echo $result             
20
[root@stone ~]# result=$(( num1 + num2 ))
[root@stone ~]# echo $result             
20
[root@stone ~]# result=$(( $num1 + $num2  ))       
[root@stone ~]# echo $result                
20

浮点运算:bc
[root@stone ~]# echo "2*3.14" | bc
6.28
[root@stone ~]# echo "scale=2;2/3" | bc         
.66
#scale设定小数点后的位数
[root@stone ~]# num=100;echo "obase=2;$num" | bc
1100100
#将十进制转化为二进制
[root@stone ~]# num=1100100;echo "obase=10;ibase=2;$num" | bc     
100
#将二进制转化为十进制
[root@stone ~]# echo "sqrt(100)" | bc
10
#开方
[root@stone ~]# echo "10^2" | bc 
100
#指数

4、文件描述符与重定向
文件描述符0——stdin(标准输入)
文件描述符1——stdout(标准输出)
文件描述符2——stderr(标准错误)
tee:从标准输入中读取数据然后标准输出并保存到文件中, 用在既想把输出保存到文件中,又想在屏幕上看到输出内容。

格式:tee

只输出到标准输出,因为没有指定文件嘛。

格式:tee file

输出到标准输出的同时,保存到文件file中。如果文件不存在,则创建;如果已经存在,则覆盖之。(If a file being written to does not already exist, it is created. If a file being written to already exists, the data it previously
contained is overwritten unless the `-a' option is used.)

格式:tee -a file

输出到标准输出的同时,追加到文件file中。如果文件不存在,则创建;如果已经存在,就在末尾追加内容,而不是覆盖。

格式:tee -

输出到标准输出两次。(A FILE of `-' causes `tee' to send another copy of input to standard output, but this is typically not that useful as the copies are interleaved.)

格式:tee file1 file2 -

输出到标准输出两次,同时保存到file1和file2中。

 

 tee命令与重定向的对比

 

 

[root@stone ~]# cat num

1

2

[root@stone ~]# cat num > num1

[root@stone ~]# cat num | tee num2

1

2

[root@stone ~]# cat num1

1

2

[root@stone ~]# cat num2

1

2

[root@stone ~]# cat num >> num1

[root@stone ~]# cat num | tee -a num2

1

2

[root@stone ~]# cat num1

1

2

1

2

[root@stone ~]# cat num2

1

2

1

2

 

 

 

使用tee命令重复输出字符串

 

 

[root@stone ~]# echo 1234 | tee

1234

[root@stone ~]# echo 1234 | tee -

1234

1234

[root@stone ~]# echo 1234 | tee - -

1234

1234

1234

[root@stone ~]# echo 1234 | tee - - -

1234

1234

1234

1234

[root@stone ~]# echo -n 1234 | tee - - -

1234123412341234[root@stone ~]# 

 

使用tee命令把标准错误输出也保存到文件

[root@stone ~]# ls aaa
ls: aaa: No such file or directory
[root@stone ~]# ls aaa | tee -
ls: aaa: No such file or directory
[root@stone ~]# ls aaa | tee ls.txt
ls: aaa: No such file or directory
[root@stone ~]# cat ls.txt
#默认仅保存标准输入
[root@stone ~]# ls aaa 2>&1 | tee ls.txt
ls: aaa: No such file or directory
[root@stone ~]# cat ls.txt
ls: aaa: No such file or directory
#以上例子参考:http://codingstandards.iteye.com/blog/833695

5、数组
#定义数组
[root@stone ~]# array_var=(1 2 3 4)
#打印特定数组元素
[root@stone ~]# echo ${array_var[0]}
1
[root@stone ~]# index=3
[root@stone ~]# echo ${array_var[$index]}
4
#打印所有数组元素
[root@stone ~]# echo ${array_var[*]}     
1 2 3 4
[root@stone ~]# echo ${array_var[@]}
1 2 3 4
#打印数组长度(数组中元素个数)
[root@stone ~]# echo ${#array_var[*]}
4
[root@stone ~]# echo ${#array_var[@]}
4

#显示目前有值的数组序号

echo ${!FILE[@]}

0 1 2


6、日期、时间与延时
日期时间格式字符串列表
日期时间
格式字符串
%y(例如:13) %Y(例如:2013)
%b(例如:Nov)%B(例如:November) %m(例如:10)
%d(例如:31)
%H(例如:14)
%M(例如:30)
%S(例如:10)
mm/dd/yy%D(例如:04/28/13)
星期%a(例如:Sat) %A(例如:saturday)
UNIX时间(单位:秒)%s
[root@stone ~]# date +%s
1367831238
[root@stone ~]# date "+%d %B %Y"
06 May 2013

延时:sleep
[root@stone ~]# sleep 10
[root@stone ~]# cat bin/sleep.sh 
#!/bin/bash
#filename:sleep.sh

echo -n count:
tput sc        #存储终端光标位置
count=0

while true
do
if [ $count -lt 40 ]; then
let count++
sleep 1
tput rc       #恢复光标位置
tput ed      #删除当前光标位置到行尾的所有内容
echo -n $count
else 
exit 0
fi
done

7、脚本调试
shell的调试选项如下:

-n 只读取shell脚本,但不实际执行
-x 进入跟踪方式,显示所执行的每一条命令
-c "string" 从strings中读取命令

shell可用于调试的内置环境变量:

$LINENO
代表shell脚本的当前行号,类似于C语言中的内置宏__LINE__

$FUNCNAME
函数的名字,类似于C语言中的内置宏__func__,但宏__func__只能代表当前所在的函数名,而$FUNCNAME的功能更强大,它是一个数组变量,其中包含了整个调用链上所有的函数的名字,故变量${FUNCNAME[0]}代表shell脚本当前正在执行的函数的名字,而变量${FUNCNAME[1]}则代表调用函数${FUNCNAME[0]}的函数的名字,余者可以依此类推。

$PS4
主提示符变量$PS1和第二级提示符变量$PS2比较常见,但很少有人注意到第四级提示符变量$PS4的作用。我们知道使用“-x”执行选项将会显示shell脚本中每一条实际执行过的命令,而$PS4的值将被显示在“-x”选项输出的每一条命令的前面。在Bash Shell中,缺省的$PS4的值是"+"号。(现在知道为什么使用"-x"选项时,输出的命令前面有一个"+"号了吧?)。利用$PS4这一特性,通过使用一些内置变量来重定义$PS4的值,我们就可以增强"-x"选项的输出信息。例如先执行export PS4='+{$LINENO:${FUNCNAME[0]}} ', 然后再使用“-x”选项来执行脚本,就能在每一条实际执行的命令前面显示其行号以及所属的函数名。

#首先使用-n选项检查语法错误

[root@stone ~]# sh -n bin/sleep.sh 

#使用-x选项追踪脚本执行

[root@stone ~]# sh -x bin/sleep.sh 

+ echo -n count:

count:+ tput sc

+ tput ed

+ echo -n 40

40+ true

+ '[' 40 -lt 40 ']'

+ exit 0  

#打印出程序的行号
[root@stone ~]# cat -n bin/sleep.sh 
     1  #!/bin/bash
     2  #filename:sleep.sh
     3
     4  echo -n count:
     5  tput sc
     6  count=0
     7
     8  while true
     9  do
    10  if [ $count -lt 40 ]; then
    11  let count++
    12  sleep 1
    13  tput rc
    14  tput ed
    15  echo -n $count
    16  else 
    17  exit 0
    18  fi
    19  done
#重新定义PS4变量
[root@stone ~]# export PS4='+{$LINENO}'
[root@stone ~]# sh -x bin/sleep.sh
+{4}echo -n count:
count:+{5}tput sc
+{14}tput ed
+{15}echo -n 40
40+{8}true
+{10}'[' 40 -lt 40 ']'
+{17}exit 0
#上面调试的结果增加了脚本的行号
调试shell脚本的过程:
首先使用“-n”选项检查语法错误,然后使用“-x”选项跟踪脚本的执行,使用“-x”选项之前,别忘了先定制PS4变量的值来增强“-x”选项的输出信息,至少应该令其输出行号信息(先执行export PS4='+[$LINENO]',更一劳永逸的办法是将这条语句加到您用户主目录的.bash_profile文件中去),这将使你的调试之旅更轻松。也可以利用trap,调试钩子等手段输出关键调试信息,快速缩小排查错误的范围,并在脚本中使用“set -x”及“set +x”对某些代码块进行重点跟踪。这样多种手段齐下,相信您已经可以比较轻松地抓出您的shell脚本中的臭虫了。如果您的脚本足够复杂,还需要更强的调试能力,可以使用shell调试器bashdb,这是一个类似于GDB的调试工具,可以完成对shell脚本的断点设置,单步执行,变量观察等许多功能,使用bashdb对阅读和理解复杂的shell脚本也会大有裨益。

8、函数和参数
定义函数:
function fname()
{
    statements;
}
或者:
fname()
{
    statements;
}

调用函数:
fname;
fname arg1 arg2;

函数参数:
fname
arg1
arg2
arg3
$0
$1
$2
$3
  • $# :代表后接的参数『个数』,以上表为例这里显示为『 3 』;

  • $@ :代表『 "$1" "$2" "$3" 』之意,每个变量是独立的(用双引号括起来);

  • $* :代表『 "$1c$2c$3" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3" 』之意。(不常用)

导出函数:
export -f fname
函数返回值:
函数返回值保存在变量?,命令成功退出,返回0,否则返回非0
[root@stone ~]# echo $?
0

9、引用 命令的输出
方式一:子shell方式
[root@stone ~]# cmd_output=$(ls | cat -n | head -5)
[root@stone ~]# echo $cmd_output
1 acltest1 2 anaconda-ks.cfg 3 a.out 4 awk.txt 5 awstats-7.1.1
方式二:反引用方式
[root@stone ~]# cmd_output=`ls | cat -n | head -3`
[root@stone ~]# echo $cmd_output                  
1 acltest1 2 anaconda-ks.cfg 3 a.out
上面两种方式均去掉了换行符(\n),参考下面的IFS,echo输出时加上双引号可保留空格和换行符。
[root@stone ~]# cmd=`ls | cat -n | head -5`
[root@stone ~]# echo "$cmd"
     1  acltest1
     2  anaconda-ks.cfg
     3  a.out
     4  awk.txt
     5  awstats-7.1.1

10、读取键盘输入:read
常用选项:
选项
含义
-n
限定输入字符长度
-t限定输入字符等待时间
-d定义输入结束符
-s
不显示输入字符
-p
增加提示信息
#限定输入字符长度为5
[root@stone ~]# read -n 5 var
12345[root@stone ~]# echo $var
12345
#限定输入等待时间为5s
[root@stone ~]# read -t 5 var
123456[root@stone ~]# 
#定义输入结束符为”:“
[root@stone ~]# read -d ":" var
123:[root@stone ~]# echo $var
123
#不显示输入字符,可用于密码输入
[root@stone ~]# read -s var
[root@stone ~]# echo $var
123456
#增加提示信息
[root@stone ~]# read -p "enter input:" var
enter input:12345
[root@stone ~]# echo $var
12345

11、内部域分隔符:IFS(Internal Field Seprator)

 Shell 的环境变量分为 set, env 两种,其中 set 变量可以通过 export 工具导入到 env 变量中。其中,set 是显示设置shell变量,仅在本 shell 中有效;env 是显示设置用户环境变量 ,仅在当前会话中有效。换句话说,set 变量里包含了 env 变量,但 set 变量不一定都是 env 变量。这两种变量不同之处在于变量的作用域不同。显然,env 变量的作用域要大些,它可以在 subshell 中使用。

     而 IFS 是一种 set 变量,当 shell 处理"命令替换"和"参数替换"时,shell 根据 IFS 的值,默认是 space, tab, newline 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。

[root@stone ~]# set | grep IFS
IFS=$' \t\n'
[root@stone ~]# echo -n "$IFS"
#直接查看IFS变量默认值为空白
[root@stone ~]# echo -n "$IFS" | od -a
0000000  sp  ht  nl
0000003
#对比ascII码表可知IFS的默认值,sp为空格符,ht为横向制表符,nl为换行符

IFS的作用是把变量中对应存在的IFS值转换成空格

如果IFS就是空格,那么类似于" [space][space]a[space]b[space][space]c "会合并重复的部分,且去头空格,去尾空格,那么最终输出会变成类似 a[space]b[space]c ,所以,如果IFS是默认值,那么处理的结果就很好算出来,直接合并、忽略多余空格即可!


[root@stone ~]# IFS=:
[root@stone ~]# echo "$IFS"
:
[root@stone ~]# set x y z
#设置x y z三个参数
[root@stone ~]# echo $*
x y z
#进行IFS替换
[root@stone ~]# echo "$*"
x:y:z
# 不进行IFS替换,故前面 echo -n "$IFS"这条语句中的$IFS需要加上双引号,才能看到起内容。
[root@stone ~]# echo $@
x y z
# $@ :代表『 "$1" "$2" "$3" 』之意,每个变量是独立的(用双引号括起来);
[root@stone ~]# echo "$@"
x y z

[root@stone ~]# set "x" "y z"
#设置x 和”y z“两个参数
[root@stone ~]# echo $*
x y z
[root@stone ~]# echo "$*"
x:y z
[root@stone ~]# echo $@
x y z
[root@stone ~]# echo "$@"
x y z
[root@stone ~]# echo $* | od -a
0000000   x  sp   y  sp   z  nl
0000006
#进行IFS替换
[root@stone ~]# echo "$*" | od -a
0000000   x   :   y  sp   z  nl
0000006
#不进行IFS替换

小结:$* 会根据 IFS 的不同来组合值,而 $@ 则会将值用" "(空格)来组合值!

[root@stone ~]# var=" : a:b:c::"
[root@stone ~]# echo -n $var | od -a
0000000  sp  sp  sp   a  sp   b  sp   c  sp
0000011
#进行IFS替换,最后两个”::“,由于后面没有其他字符,替换为一个sp
[root@stone ~]# echo -n "$var" | od -a
0000000  sp   :  sp   a   :   b   :   c   :   :
0000012
#不进行IFS替换

[root@stone ~]# for x in $var ;do echo -n $x |od -a ;done
0000000  sp
0000001
0000000  sp   a
0000002
0000000   b
0000001
0000000   c
0000001
#以”:“作为变量分割

[root@stone ~]# vim bin/ifstest 

  1 #!/bin/bash
  2  output_args_ifs(){
  3     echo "=$*"  
  4     echo "="$*  
  5     for m in $* ;do
  6         echo "[$m]"  
  7     done
  8 }
  9 
 10 IFS=':'
 11 var='::a:b::c:::::'
 12 output_args_ifs $var
[root@stone ~]# ifstest         
=::a:b::c::::
=  a b  c   
[]
[]
[a]
[b]
[]
[c]
[]
[]
[]

[root@stone ~]# read var
       aaa      bbb
[root@stone ~]# echo $var
aaa bbb
[root@stone ~]# echo "$var"
aaa      bbb
[root@stone ~]# read
   aaa   bbb   
[root@stone ~]# echo "$REPLY"
   aaa   bbb   

总结:
IFS的作用是把变量中对应存在的IFS值转换成空格
IFS值默认为空白,包括 sp为空格符,ht为横向制表符,nl为换行符
如果变量引用时加上双引号,则不替换
$* 会根据 IFS 的不同来组合值,而 $@ 则会将值用" "(空格)来组合值
在函数中,由于$@中不包含IFS,故建议使用$@
不建议对IFS变量进行更改,特殊情况可使用$REPLY输出空格

12、判断与条件语句
使用test判断
测试的标志代表意义
1. 关於某个档名的『文件类型』判断,如 test -e filename 表示存在否
-e该『档名』是否存在?(常用)
-f该『档名』是否存在且为文件(file)?(常用)
-d该『档名』是否存在且为目录(directory)?(常用)
-b该『档名』是否存在且为一个 block device 装置?
-c该『档名』是否存在且为一个 character device 装置?
-S该『档名』是否存在且为一个 Socket 文件?
-p该『档名』是否存在且为一个 FIFO (pipe) 文件?
-L该『档名』是否存在且为一个连结档?
2. 关於文件的权限侦测,如 test -r filename 表示可读否 (但 root 权限常有例外)
-r侦测该档名是否存在且具有『可读』的权限?
-w侦测该档名是否存在且具有『可写』的权限?
-x侦测该档名是否存在且具有『可运行』的权限?
-u侦测该档名是否存在且具有『SUID』的属性?
-g侦测该档名是否存在且具有『SGID』的属性?
-k侦测该档名是否存在且具有『Sticky bit』的属性?
-s侦测该档名是否存在且为『非空白文件』?
3. 两个文件之间的比较,如: test file1 -nt file2
-nt(newer than)判断 file1 是否比 file2 新
-ot(older than)判断 file1 是否比 file2 旧
-ef判断 file1 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode 哩!
4. 关於两个整数之间的判定,例如 test n1 -eq n2
-eq两数值相等 (equal)
-ne两数值不等 (not equal)
-gtn1 大於 n2 (greater than)
-ltn1 小於 n2 (less than)
-gen1 大於等於 n2 (greater than or equal)
-len1 小於等於 n2 (less than or equal)
5. 判定字串的数据
test -z string判定字串是否为 0 ?若 string 为空字串,则为 true
test -n string判定字串是否非为 0 ?若 string 为空字串,则为 false。
注: -n 亦可省略
test str1 = str2判定 str1 是否等於 str2 ,若相等,则回传 true
test str1 != str2判定 str1 是否不等於 str2 ,若相等,则回传 false
6. 多重条件判定,例如: test -r filename -a -x filename
-a(and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。
-o(or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。
!反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true

使用[]进行判断

条件判断:
if条件
if [ condition ];then

fi

if...else条件
if [ condition ];then

else

fi

if...elseif...else条件
if [ condition ];then

elseif [ condition ];then

else

fi

13、循环语句
while循环
while [condition]
do

done

until循环
until [condition]
do

done

for循环
for var in list
do

done

14、bash中的通配符与特殊符号

在 bash 的操作环境中还有一个非常有用的功能,那就是通配符 (wildcard) ! 我们利用 bash 处理数据就更方便了!底下我们列出一些常用的通配符喔:

符号意义
*代表『 0 个到无穷多个』任意字符
?代表『一定有一个』任意字符
[ ]同样代表『一定有一个在括号内』的字符(非任意字符)。例如 [abcd] 代表『一定有一个字符, 可能是 a, b, c, d 这四个任何一个』
[ - ]若有减号在中括号内时,代表『在编码顺序内的所有字符』。例如 [0-9] 代表 0 到 9 之间的所有数字,因为数字的语系编码是连续的!
[^ ]若中括号内的第一个字符为指数符号 (^) ,那表示『反向选择』,例如 [^abc] 代表 一定有一个字符,只要是非 a, b, c 的其他字符就接受的意思。

接下来让我们利用通配符来玩些东西吧!首先,利用通配符配合 ls 找檔名看看:

[root@www ~]# LANG=C            <==由于与编码有关,先配置语系一下范例一:找出 /etc/ 底下以 cron 为开头的档名
[root@www ~]# ll -d /etc/cron*  <==加上 -d 是为了仅显示目录而已范例二:找出 /etc/ 底下文件名『刚好是五个字母』的文件名
[root@www ~]# ll -d /etc/?????  <==由于 ? 一定有一个,所以五个 ? 就对了范例三:找出 /etc/ 底下文件名含有数字的文件名
[root@www ~]# ll -d /etc/*[0-9]*<==记得中括号左右两边均需 *范例四:找出 /etc/ 底下,档名开头非为小写字母的文件名:
[root@www ~]# ll -d /etc/[^a-z]*<==注意中括号左边没有 *范例五:将范例四找到的文件复制到 /tmp 中
[root@www ~]# cp -a /etc/[^a-z]* /tmp

除了通配符之外,bash 环境中的特殊符号有哪些呢?底下我们先汇整一下:

符号内容
#批注符号:这个最常被使用在 script 当中,视为说明!在后的数据均不运行
\跳脱符号:将『特殊字符或通配符』还原成一般字符
|管线 (pipe):分隔两个管线命令的界定(后两节介绍);
;连续命令下达分隔符:连续性命令的界定 (注意!与管线命令并不相同)
~用户的家目录
$取用变量前导符:亦即是变量之前需要加的变量取代值
&工作控制 (job control):将命令变成背景下工作
!逻辑运算意义上的『非』 not 的意思!
/目录符号:路径分隔的符号
>, >>数据流重导向:输出导向,分别是『取代』与『累加』
<, <<数据流重导向:输入导向 (这两个留待下节介绍)
' '单引号,不具有变量置换的功能
" "具有变量置换的功能!
` `两个『 ` 』中间为可以先运行的命令,亦可使用 $( )
( )在中间为子 shell 的起始与结束
{ }在中间为命令区块的组合!

以上为 bash 环境中常见的特殊符号汇整!理论上,你的『档名』尽量不要使用到上述的字符啦!

摘自《鸟哥私房菜》