注意$variable事实上只是${variable}的简写形式。赋值时如果在变量中存在空白,那么就必须加上引用.other_numbers=1 2 3 # 给出一个错误消息.
一个未初始化的变量是没有值的, 但是在做算术操作的时候, 这个未初始化的变量看起来值为0. 这是一个未文档化(并且可能不具可移植性)的行为.
cut , sort,join这些命令智能用单个分隔符,如果要用转义字符做分隔则可以用-t/d $' '的形式。awk则可以直接用-F' '的形式,并且支持正则表达式。但是用"^&"作为分隔符时,必须只用-F'\^&',单引号双斜杠,换成双引号或者单斜杠转义都不行。
%在crontab中被认为是newline,要用来escape才行。比如crontab执行行中,如果有"date +%Y%m%d",必须替换为:"date +\%Y\%m\%d"
47 09 * * * cd /fourthinfo/zhaoxiang/zp_user && echo "this is a test" > "logs/$(date +\%Y-\%m-\%d_\%H:\%M:\%S).log" 2>&1
1 {xxx,yyy,zzz,...} 大括号扩展. 3 cat {file1,file2,file3} > combined_file # 把file1, file2, file3 连接在一起, 并且重定向到combined_file中. 4 cp file22.{txt,backup} # 拷贝"file22.txt"到"file22.backup" 中 5 一个命令可能会对大括号中的以逗号分割的文件列表起作用. (通配(globbing) )将对大括号中的文件名做扩展. 6 在大括号中, 不允许有空白, 除非这个空白被引用或转义. 7 echo {file1,file2} :{ A," B",' C'} 8 file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C 9 10 $' ... ' 11 Quoted string expansion. This construct expands single or multiple escaped octal or hex values into ASCII [18] or Unicode characters. 12 13 {a..z} Extended Brace expansion. 14 echo {a..z} # a b c d e f g h i j k l m n o p q r s t u v w x y z # Echoes characters between a and z. 15 echo {0..3} # 0 1 2 3 16 base64_charset=( {A..Z} {a..z} {0..9} + / = ) # Initializing an array, using extended brace expansion. 17 The {a..z} extended brace expansion construction is a feature introduced in version 3 of Bash.
正则强引用问题 1 sed -e '/^$/d' $filename 2 # -e选项, 将会使得后边的字符被看作为编辑指令. (如果只给"sed"传递了单个指令, 那么"-e"是可选的.) 4 # "强"引用('')将会保护指令中的RE(正则表达式)字符串, 也就是防止脚本将RE重新解释为特殊字符. (这会为sed命令, 保存指令的RE表达式.) 在某些特定的情况下, sed编辑命令将不会和单引号的强引用一起工作. 1 filename=file1.txt 2 pattern=BEGIN 3 4 sed "/^$pattern/d" "$filename" # 工作正常. 5 # sed '/^$pattern/d' "$filename" 就会出现异常的结果. 在这个实例中, 被强引用(' ... ')引起的 "$pattern"就不会扩展为"BEGIN". sed -n '/xzy/p' $filename # -n选项会让sed只打印那些匹配模式的行. 反斜线将会强制sed替换命令延续到下一行. 类似于, 在第一行的结尾使用换行作为替换字符串. 1 s/^ */ 2 /g 这将每行开头的空格用换行来替换. 最后的结果就是将每段的缩进替换为一个空行。
通常,正则表达式需要用单引号括起来,阻止特殊字符被解释,而通配符不能用引号。 单引号中的所有字符包括都没有特殊意义。如果想在一对单引号中显示一个单引号是不行的
在一个双引号中通过直接使用变量名的方法来引用变量, 一般情况下都是没问题的. 这么做将阻止所有在引号中的特殊字符被重新解释 -- 包括变量名 [1]-- 但是$,`(后置引用), 和(转义符)除外。使用双引号还能够阻止单词分割(word splitting). [3]如果一个参数被双引号扩起来的话, 那么这个参数将认为是一个单元, 即使这个参数包含有空白, 那里面的单词也不会被分隔开。
在echo语句中, 只有在单词分割(word splitting)或者需要保留空白的时候, 才需要把参数用双引号括起来.
使用-e选项的'echo'命令来打印转义符. echo -e "vvvv" # 打印4个垂直制表符.
如果使用$'X'结构,那-e选项就不必要了. echo $' 42 ' # 被水平制表符括起来的引号(").
variable2="" # Empty.
COMMAND $variable2 $variable2 $variable2 # COMMAND将不带参数执行.
COMMAND "$variable2" "$variable2" "$variable2" # COMMAND将以3个空参数来执行.
COMMAND "$variable2 $variable2 $variable2" # COMMAND将以1个参数来执行(2空格)
file_list="/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7" # 列出的文件都作为命令的参数
ls -l /usr/X11R6/bin/xsetroot /sbin/dump $file_list # 加两个文件到参数列表中, 列出所有的文件信息.
(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)
每个命令都会返回一个 退出状态码 (有时候也被称为 返回状态 ). 成功的命令返回0, 而不成功的命令返回非零值, 非零值通常都被解释成一个错误码,虽然偶尔也会有例外。exit nnn命令将会把 nnn退出码传递给shell( nnn必须是十进制数, 范围必须是0- 255)。
(( ... ))和let ...结构也能够返回退出状态码, 当它们所测试的算术表达式的结果为非零的时候, 将会返回退出状态码0. 这些算术扩展结构被用来做算术比较.
在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割, 但是会发生参数扩展和命令替换. 使用[[ ... ]]条件判断结构, 而不是[ ... ], 能够防止脚本中的许多逻辑错误. 比如,&&, ||, <, 和>操作符能够正常存在于[[ ]]条件判断结构中, 但是如果出现在[ ]结构中的话, 会报错.
"if COMMAND"结构将会返回COMMAND的退出状态码. 与此相似, 在中括号中的条件判断也不一定非得要if不可, 也可以使用列表结构.
[ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2"
home=/home/bozo
[ -d "$home" ] || echo "$home directory does not exist."
(( ))结构扩展并计算一个算术表达式的值. 如果表达式的结果为0, 那么返回的退出状态码为1, 或者是"假". 而一个非零值的表达式所返回的退出状态码将为0, 或者是"true". 这种情况和先前所讨论的test命令和[ ]结构的行为正好相反。
当-n使用在中括号中进行条件测试的时候, 必须要把字符串用双引号引用起来,习惯于使用引用的测试字符串才是正路。
变量的间接引用
var1=var2
var 2=value
(1) eval tmpvar=$$var1
(2) tmpvar=${!var1}
在awk中调用linux命令,要用双引号引起来。 awk -F: '{print $1 | "sort"}' /etc/passwd
子shell能继承父shell的一些属性,但是不可能改变父shell的属性。
shell默认将变量看作只有一个元素的数组,而@和*都可用于数组。
nameList=`wget "$reqUrl" -O- 2>/dev/null|grep -Po '(?<=:9000">)[^/]*?(?=</a></B><br></td>)'|sed '/^_/d'` while read name do downFileFullName=$baseHdfsPath/$name tmpUrl="http://localhost:50075/streamFile$downFileFullName?nnaddr=host:9000" wget "$tmpUrl" -O $name done< <(echo "$nameList") #进程替换
echo "$nameList" | while read name #管道,在这里不能用命令替换,命令替换把一个进程的输出赋值给一个变量。 do downFileFullName=$baseHdfsPath/$name tmpUrl="http://localhost:50075/streamFile$downFileFullName?nnaddr=host:9000" wget "$tmpUrl" -O $name done
- 用于重定向stdin或stdout,相当于一个文件名。 (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)
grep Linux file1 | diff file2 -
Bash变量是不区分类型的
a=2334 # 整型. 5 let "a += 1" 6 echo "a = $a " # a = 2335 7 echo # 还是整型. 8 9 10 b=${a/23/BB} # 将"23"替换成"BB". 11 # 这将把变量b从整型变为字符串. 12 echo "b = $b" # b = BB35 13 declare -i b # 即使使用declare命令也不会对此有任何帮助. 14 echo "b = $b" # b = BB35 15 16 let "b += 1" # BB35 + 1 = 17 echo "b = $b" # b = 1 18 echo 19 20 c=BB34 21 echo "c = $c" # c = BB34 22 d=${c/BB/23} # 将"BB"替换成"23". 23 # 这使得变量$d变为一个整形. 24 echo "d = $d" # d = 2334 25 let "d += 1" # 2334 + 1 = 26 echo "d = $d" # d = 2335 27 echo 28 29 # null变量会如何呢? 30 e="" 31 echo "e = $e" # e = 32 let "e += 1" # 算术操作允许一个null变量? 33 echo "e = $e" # e = 1 34 echo # null变量将被转换成一个整型变量. 35 36 # 如果没有声明变量会怎样? 37 echo "f = $f" # f = 38 let "f += 1" # 算术操作能通过么? 39 echo "f = $f" # f = 1 40 echo # 未声明的变量将转换成一个整型变量. # 所以说Bash中的变量都是不区分类型的.
{}标记法提供了一种提取从命令行传递到脚本的最后一个位置参数的简单办法. 但是这种方法同时还需要使用间接引用.
1 args=$# # 位置参数的个数. 2 lastarg=${!args} 3 # 或: lastarg=${!#} 4 # (感谢, Chris Monson.) 5 # 注意, 不能直接使用lastarg=${!$#} , 这会产生错误.
参数替换好方法: ${1:-$DefaultVal}
引用可以阻止单词分割,还可以改掉echo's不换行的"毛病".
bash$ echo $(ls -l) total 8 -rw-rw-r-- 1 bozo bozo 130 Aug 21 12:57 t222.sh -rw-rw-r-- 1 bozo bozo 78 Aug 21 12:57 t71.sh bash$ echo "$(ls -l)" total 8 -rw-rw-r-- 1 bozo bozo 130 Aug 21 12:57 t222.sh -rw-rw-r-- 1 bozo bozo 78 Aug 21 12:57 t71.sh
8
9 variable2="" # Empty.
10
11 COMMAND $variable2 $variable2 $variable2 # COMMAND将不带参数执行.
12 COMMAND "$variable2" "$variable2" "$variable2" # COMMAND将以3个空参数来执行.
13 COMMAND "$variable2 $variable2 $variable2" # COMMAND将以1个参数来执行(2空格).
即使是转义符()在单引号中也是按照字面意思解释的, 所以如果想在一对单引号中显示一个单引号是不行的。
echo "Why can't I write 's between single quotes" # 一种绕弯的方法. echo 'Why can'''t I write '"'"'s between single quotes' # |-------| |----------| |-----------------------| # 三个被单引号引用的字符串, 在这三个字符串之间有一个用转义符转义的单引号, 和一个用双引号括起来的单引号
转义字符
echo -e "