shell高级编程笔记(第五章 引用(引号))

    技术2022-07-13  79

    第五章 引用(引号)

    引号的特殊效果就是保护字符串中的特殊字符不被shell或shell脚本重新解释或者扩展。 (这里所说的"特殊"指的是一些字符在shell中具有特殊的意义,比如:*)

    [root@localhost aaa]# ls 1.sh 2.txt file.txt File.txt [root@localhost aaa]# ls [Ff]* file.txt File.txt [root@localhost aaa]# ls '[Ff]*' ls: 无法访问[Ff]*: 没有那个文件或目录

    特定的程序和工具能够重新解释或者扩展特殊的字符。引号的一个重要的作用就是保护命令行的参数,但还是允许正在调用的程序来扩展它

    grep '[Ff]irst' *.txt file1.txt:This is the first of file1.txt file2.txt:This is the First of file2.txt #grep [Ff]irst *.txt 在Bash下的行为也是这样(正则)

    引号还可以抑制echo命令的换行作用

    [root@localhost aaa]# echo $(ls -l) 总用量 4 -rwxr-xr-x 1 root root 64 5月 28 01:57 1.sh -rw-r--r-- 1 root root 0 6月 22 18:38 2.txt [root@localhost aaa]# echo "$(ls -l)" 总用量 4 -rwxr-xr-x 1 root root 64 5月 28 01:57 1.sh -rw-r--r-- 1 root root 0 6月 22 18:38 2.txt

    5.1 引用变量

    在一个双引号中直接使用变量名一般都是没有问题的。它阻止了所有在引号中的特殊字符的重新解释(包括变量名),但是$、`和\除外。 $ 作为特殊字符的意义,是为了能够在双引号中也能正常地引用变量。这样在""中可以使用变量表达式的值(Example 4.1)

    使用""来防止单词分割。如果在参数列表中使用双引号,将使得双引号中的参数作为一个参数。即使双引号中的字符串包含多个单词,也不会边为多个参数。如:

    variable1="a variable containing five words" COMMAND This is $variable1 #COMMAND将以7个参数来执行 #"This" "is" "a" "variable" "containing" "five" "words" COMMAND "This is $variable1" #COMMAND将以1个参数来执行 #"This is a variable containing five words" variable2="" COMMAND $variable2 $variable2 $variable2 #COMMADN将不带参数执行 COMMAND "$variable2" "$variable2" "$variable2" #COMMADN将以3个空参数去执行 COMMAND "$variable2 $variable2 $variable2" #COMMADN将以1个参数(2个空格)执行

    用双引号把参数封到echo中是很有必要的,只有在单词分隔时或保留空白时可能有些问题。 Example 5.1 echo 一些诡异的变量

    #!/bin/bash #weiravars.sh:echo 诡异的变量 var="'(]\\{}\$\"" echo $var #'(]\{}$" echo "$var" #'(]\{}$" IFS='\' echo $var #'(] {}$" \转换成了空格 echo "$var" #'(]\{}$" exit 0

    IFS

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

    [root@localhost ~]# echo "$IFS" #直接输出IFS看不到值 [root@localhost ~]# echo "$IFS" | od -b #转化为二进制就可以看到了 0000000 040 011 012 012 0000004 #"040"是空格,"011"是Tab,"012"是换行符"\n" #最后一个 012 是因为 echo 默认是会换行的

    实际应用中

    #!/bin/bash OLD_IFS=$IFS #保存原始值 IFS="" #改变IFS的值 ... ... IFS=$OLD_IFS #还原IFS的原始值

    5.2 转义 ()

    转义是一种引用单个字符的方法。一个具有特殊含义的字符前边放上一个转义字符()就告诉shell这个字符失去了特殊的含义。 值得注意的是,在某些特定的命令和工具中,比如echo和sed,转义字符往往会起到相反的效果,它反倒有可能引发出这个字符特殊的含义。 在echo和sed中所使用的含义 \n #意味着新的一行 \r #回车 \t #tab键 \v #vertical tab(垂直tab),查看前边的Ctl-K \b #backspace,查看前边的Ctl-H \a #alert(如beep或flash) \0xx #转换成8进制ASCII解码,等价于oxx

    Example 5.2 转义字符

    #!/bin/bash #escaped.sh:转义字符 echo "\v\v\v\v" #\v\v\v\v echo -e "\v\v\v\v" #echo -e是输出转义字符,所以会输出4个垂直tab echo "=====================" echo -e "\042" #"("的8进制ASCII码是42) echo "=====================" #如果使用''($'\x')结构,就不需要-e了 echo $'\n' #新行 echo $'\a' #alert echo "=====================" #8进制,结构是$'\nnn' #[root@zhhs ~]# echo $'\t \042 \t' # " #16进制,结构是$'\xhhh' #[root@zhhs ~]# echo $'\t \x22 \t' # " #分配ASCII字符到变量中 quote=$'\042' echo "$quote This is a quoted string,$quote and this lies outside the quotes." #" This is a quoted string," and this lies outside the quotes. #变量中连续的ASCII char。 triple_underline=$'\137\137\137' #137是'_'的八进制ASCII码。 echo "$triple_underline UNDERLINE $triple_underline" #___ UNDERLINE ___ exit 0

    另一个关于$"字符串扩展的例子见Example 34.1

    \" 表达引号本身 echo "Hello" #Hello echo "\"Hello\",he said" #"Hello",he said \$ $号本身,跟在\$后的变量名,将不能扩展 echo "\$variable" #$variable \\ \号本身 echo "\\" #\ #相反的 echo "\" #这会出现第二个命令提示符,说白了就是提示你命令不全,还需要一个",如果是在脚本里,就会给出一个错误

    分配给变量的字符串的元素也会被转义,但是只把一个转义字符分配给变量将会报错。

    variable=\ 123qwe echo "$variable" #123qwe。这里"\"被认为是一个续行符 variable=\ #转义一个空格 echo "$variable" #显示空格 #variable=\\\和variable=\是一样的,都是非法定义;但是variable=\\\\是可以的 variable=\\\\ echo "$variable" #\\ #转义一个空格,在命令行参数列表中将会阻止单词分割问题 ls -l /usr/local\ /bin/xsetroot\ /sbin/dump #这里转义空格,会将/usr/local /bin/xsetroot /sbin/dump作为一个参数传递给ls -l

    转义字符的续行功能

    (cd /source/directory && tar -cf - .) | \ (cd /dest/directory && tar xpvf -) #也可以使用如下方式: tar cf - -C /source/directory . | tar xpvf - -C /dest/directory

    注意:如果一个脚本以|(管道)结束,那么一个(转义字符)就不用了非加不可了;但是一个好的shell脚本编写风格还是应该在行尾加上\,以增加可读性。

    echo "foo bar" #foo #bar echo 'foo bar' #foo #bar echo foo\ bar #foobar echo "foo\ bar" #foobar echo 'foo\ bar' #foo\ #bar
    Processed: 0.010, SQL: 9