:特殊字符

Posted Dontla

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了:特殊字符相关的知识,希望对你有一定的参考价值。

原文:http://shouce.jb51.net/shell/

linux shell编程、bash编程、shell教程、bash教程、shell文档、bash文档、shell脚本、bash脚本【教程】第一章:Shell编程 第二章:Sha-Bang(#!)开始

文章目录

第二部分:基础

第三章:特殊字符

在脚本或其他别的地方出现的特殊字符

#(井号)注释

注释. 以一个#开头的行 (#!是例外) 是注释行.

# 这是一行注释.

注释也可以出现在一个命令语句的后面。

echo "A comment will follow." # 这里可以添加注释.
#                            ^ 注意在#前面可以有空白符 #

注释行前面也可以有空白字符.

	#注意这个注释行的开头是一个TAB键.

在同一行中,命令不会跟在一个注释的后面。因为这种情况下没有办法分辨注释的结尾,命令只能放在同一行的行首。用另外的一个新行开始下一个注释。

当然了,在echo命令给出的一个转义的#字符并不会开始一个注释。同样地,出现在一些参数代换结构和在数值常量表达式中的#字符也同样不会开始一个注释。

echo "The # here does not begin a comment."
echo 'The # here does not begin a comment.'
echo The \\# here does not begin a comment.
echo The # here begins a comment.

echo $PATH#*:       # 前面的#是参数代换,不是注释.
echo $(( 2#101011 ))  # 基本转换,不是注释.

# 多谢, S.C.

标准的引用和转义 符(" ' \\)可以转义#。

当然,模式匹配操作也可以使用#,而不必把它当做注释的开始。

;(分号)分割符允许在同一行里有两个或更多的命令

命令分割符[分号]. 分割符允许在同一行里有两个或更多的命令.

echo hello; echo there

if [ -x "$filename" ]; then    # 注意:"if" and "then"需要分隔符
                               # 思考一下这是为什么?
  echo "File $filename exists."; cp $filename $filename.bak
else
  echo "File $filename not found."; touch $filename
fi; echo "File test complete."

注意”;”有时需要转义.

;;(双分号)case语句分支的结束符

case语句分支的结束符[双分号].

case "$variable" in
abc)  echo "\\$variable = abc" ;;
xyz)  echo "\\$variable = xyz" ;;
esac

.(点、圆点)等同于source

"点"命令[圆点]. 等同于source (参考例子 11-20).这是一个bash的内建命令.

.(点、圆点)作为一个文件名的组成部分时,作前缀为隐藏文件;作为目录名时,单个点(.)表示当前目录,两个点(..)表示上一级目录

“点”, 作为一个文件名的组成部分.当点(.)以一个文件名为前缀时,起作用使该文件变成了隐藏文件。这种隐藏文件ls一般是不会显示出来的。[译者注:除非你加了选项-a]

bash$ touch .hidden-file
bash$ ls -l	      
total 10
-rw-r--r--    1 bozo      4034 Jul 18 22:04 data1.addressbook
-rw-r--r--    1 bozo      4602 May 25 13:58 data1.addressbook.bak
-rw-r--r--    1 bozo       877 Dec 17  2000 employment.addressbook


bash$ ls -al	      
total 14
drwxrwxr-x    2 bozo  bozo      1024 Aug 29 20:54 ./
drwx------   52 bozo  bozo      3072 Aug 29 20:51 ../
-rw-r--r--    1 bozo  bozo      4034 Jul 18 22:04 data1.addressbook
-rw-r--r--    1 bozo  bozo      4602 May 25 13:58 data1.addressbook.bak
-rw-r--r--    1 bozo  bozo       877 Dec 17  2000 employment.addressbook
-rw-rw-r--    1 bozo  bozo         0 Aug 29 20:54 .hidden-file

作为目录名时,单个点(.)表示当前目录,两个点(..)表示上一级目录(译者注:或称为父目录)。

bash$ pwd
/home/bozo/projects

bash$ cd .
bash$ pwd
/home/bozo/projects

bash$ cd ..
bash$ pwd
/home/bozo/

单点(.)文件名常常被当作文件移动命令的目的路径.

bash$ cp /home/bozo/current_work/junk/* .

.(点、圆点)作为正则表达式的一部分匹配字符时,表示匹配任意一个字符

点(.)字符匹配.作为正则表达式的一部分,匹配字符时,单点(.)表示匹配任意一个字符。

" "(双引号)部分引用,能使被引用的特殊字符被解释

部分引用[双引号]. "STRING"的引用会使STRING里的特殊字符能够被解释。请参考第五章.

示例:单引号和双引号区别(单引号不能变量替换)

#!/bin/bash

# Variables: 赋值和替换

a=375
hello=$a

echo "$hello"	# 375
echo "$hello"	# 375
echo '$hello'	# $hello
echo '$hello'	# $hello

示例:加双引号和不加的区别(双引号把变量引起来能保留空白字符.)如果没有引号,则会删除多余tab键和空白符

#!/bin/bash

hello="A B  C   D"
echo $hello   # A B C D
echo "$hello" # A B  C   D

' '(单引号)完全引用,特殊字符不会被解释

完全引用[单引号]. 'STRING’能引用STRING里的所有字符(包括特殊字符也会被原样引用). 这是一个比使用双引号(“)更强的引用。 参考第5章.

单引号与双引号区别:见上

,(逗号)用于连接一连串的数学表达式。这一串的数学表达式每一个都被求值,但只有最后一个被返回

逗号操作符[逗号]. 逗号操作符用于连接一连串的数学表达式。这一串的数学表达式每一个都被求值,但只有最后一个被返回。(译者注:换句话说,就是整个表达式的值取决于最后一个表达式的值。)

let "t2 = ((a = 9, 15 / 3))"  # Set "a = 9" and "t2 = 15 / 3"

\\(转义符,反斜杠,后斜杠)

转义符[后斜杠].用于单个字符的引用机制。

\\X "转义"字符为X.它有"引用"X的作用,也等同于直接在单引号里的'X'.\\符也可以用于引用双引号(")和单引号('),这时双引号和单引号就表示普通的字符,而不是表示引用了。

参考第五章对转义字符的更深入的解释。

/(分隔符,前斜杠)分隔文件路径的各个部分,算术操作符中的除法

文件路径的分隔符[前斜杠]. 分隔一个文件路径的各个部分。(就像/home/bozo/projects/Makefile).

它也是算术操作符中的除法.

`(后引号 backquotes、斜引号 backticks、反引号)(命令替换)(将被引住的命令(command)执行结果赋值给一个变量)【命令替换建议用$(),不要用反引号】

反引号是一个老的用法,$()是新的用法,无论是在学习还是实际工作中,建议使用$()

参考文章:Shell反引号、 ( ) 和 ()和 ()的区别

命令替换.command 结构使字符(`)[译者注:这个字符不是单引号,而是在标准美国键盘上的ESC键下面,在字符1左边,在TAB键上面的那个键,要特别留心]引住的命令(command)执行结果能赋值给一个变量。它也被称为后引号(backquotes)或是斜引号(backticks).

:(冒号)(空命令、空操作、NULL操作符)(相当于true)(在if/then的测试结构中用作占位符)(在必须要有两元操作的地方作为一个分隔符)(和重定向操作符(>)连用, 把一个文件内容清空)(环境变量域分割符)(可用于注释一行,类似#,但不推荐)

空命令[冒号]. 这个命令意思是空操作(即什么操作也不做). 它一般被认为是和shell的内建命令true是一样的。冒号":" 命令是Bash自身内建的, and its它的退出状态码是真(即0)。[译者注:shell中真用数字0表示].

(下面的echo $?表示命令执行后的状态)

:
echo $?   # 0

死循环可以这么写:

while :
do
   operation-1
   operation-2
   ...
   operation-n
done

# 等同于:
#    while true
#    do
#      ...
#    done

if/then的测试结构中用作占位符:

if condition
then :   # 什么也不做的分支
else
   take-some-action
fi

在必须要有两元操作的地方作为一个分隔符, 参考例子 8-2和默认参数.

: $username=`whoami`
# $username=`whoami`   如果没有开头的:,将会出错
#                        除非"username"是一个外部命令或是内建命令...

在here document中的一个命令作为一个分隔符. 参考例子 17-10.

在参数替换中为字符串变量赋值 (就像例子 9-14).

: $HOSTNAME? $USER? $MAIL?
#  如果列出的一个或多个基本的环境变量没有设置,
#+ 将打印出错信息。

变量扩展/子串代换.

和重定向操作符(>)连用, 可以把一个文件的长度截短为零,文件的权限不变。如果文件不存在,则会创建一个新文件。

: > data.xxx   # 文件"data.xxx"现在长度为0了	      

# 作用相同于:cat /dev/null >data.xxx(译者注:echo >data.xxx也可以)
# 但是,用NULL:)操作符不会产生一个新的进程,因为NULL操作符是内建的。

请参考例子 12-14.

和添加重定向操作符(>>)连用(: >> target_file).如果目标文件存在则什么也没有发生,如果目标文件不存在,则创建它。

这只能应用在普通文件中,不能用在管道,符号链接和其他的特殊文件。

虽然这是不被推荐的,但是NULL操作符(:)也可以用于开始注释一行。使用#来注释一行将会使Bash不会检查这行后面的语法是否有错,因此#注释几乎可以出现任何的东西。但是,对于用NULL操作符(:)注释的行则不是这样。

下面一个会产生错误的注释。

 : This is a comment that generates an error, ( if [ $x -eq 3] ).

字符”:”也用于域分割符。比如说在/etc/passwd和环境变量$PATH里.

 bash$ echo $PATH
 /usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games

!(感叹号)取反操作符,取反一个命令的退出状态,取反一个测试操作,间接变量引用,在命令行中调用属于历史命令机制的调用

取反一个测试结果或退出状态[感叹号]. 取反操作符(!)取反一个命令的退出状态(参考例子 6-2).它也取反一个测试操作。例如,它能改相等符( = )为不等符( != ).取反操作符(!)是一个Bash的关键字.

在不同的环境里,感叹号也可以出现在间接变量引用.

还有一种环境里,在命令行中,感叹号(!)调用属于历史命令机制的调用(详细请看附录 J).值得一提的是,在一个脚本里,命令历史机制是被禁止的。

*(星号)通配符,它自动匹配给定的目录下的每一个文件、用于正则表达式中匹配任意数字字符、一个*表示乘法运算符,两个星号(**)表示求幂运算符

通配符[星号].星号(*)字符在用于匹配文件名扩展的一个通配符.它自动匹配给定的目录下的每一个文件。

bash$ echo *
abs-book.sgml add-drive.sh agram.sh alias.sh

星号(*)也用于正则表达式中匹配任意数字字符。.

算术操作符. 在计算时,星号(*)表示乘法运算符。两个星号(**)表示求幂运算符。

?(问号)测试操作符,在一些表达式中表示一个条件测试、在双括号结构里表示C风格的三元操作符、在参数替换表达式里测试一个变量是否被设置了值、[通配符]被用于文件名扩展特性的文件名表达式的单字符匹配,同时也在扩展正则表达式中匹配任意一个字符

测试操作符.在一些表达式中,问号(?)表示一个条件测试.

在双括号结构里,问号(?)表示C风格的三元操作符.请参考例子 9-30.

在参数替换表达式里,问号(?)测试一个变量是否被设置了值.

通配符. 字符?被用于文件名扩展特性的文件名表达式的单字符匹配,同时也在扩展正则表达式中匹配任意一个字符.

$(美元符)变量替换,引用一个变量的内容、在正则表达式里,一个$字符表示匹配一行的结尾

变量替换 (引用一个变量的内容).

var1=5
var2=23skidoo

echo $var1     # 5
echo $var2     # 23skidoo

一个变量名前面加一个$字符前缀表示引用该变量的内容。

行的结尾. 在正则表达式里,一个$字符表示匹配一行的结尾。

$(美元符+大括号)参数替换(用$ 会比$更精确的界定变量名称的范围)如$AB最好用$AB,不然有可能会被识别成$AB

参数替换. 变量替换

$()命令替换,见前面反引号`

$*, $@位置参数,不太懂干嘛的

位置参数.

$?保存退出码值的变量,保存了一个命令,一个函数,或一个脚本的退出状态码的值

保存退出码值的变量. 变量$?保存了一个命令,一个函数,或一个脚本的退出状态码的值。

$$进程ID变量,保存了脚本运行时的进程ID值

进程ID变量. 变量$$保存了脚本运行时的进程ID值。

()命令组,一组由圆括号括起来的命令由新开的一个子shell来执行,与父shell环境隔离;数组初始化

命令组.

 (a=hello; echo $a)

一组由圆括号括起来的命令是新开一个子shell来执行的.

因为是在子shell里执行,在圆括号里的变量不能被脚本的其他部分访问。因为父进程(即脚本进程)不能存取子进程(即子shell)创建的变量。(译者注:读者若对这部分内容感兴趣,可以参考stevens的<<Advance Unix Environment Programing>>一书中对进程的描述。).

a=123
( a=321; )	      

echo "a = $a"   # a = 123
# 在圆括号里的变量"a"实际上是一个局部变量,作用局域只是在圆括号内用于数组始初化

数组初始化.

Array=(element1 element2 element3)

xxx,yyy,zzz,...(文件名)扩展支持,cat file1,file2,file3 > combined_file连接文件内容;cp file22.txt,backup创建文件备份

扩展支持.

cat file1,file2,file3 > combined_file
# 连接file1,file2,和file3的内容并写到文件combined_file里去.

cp file22.txt,backup
# 拷贝"file22.txt"内容为"file22.backup"

一个命令可以在文件名扩展中从逗号分隔的各模式来扩展参数列表。 [1] 文件名将会依照列表中逗号分隔开的模式匹配扩展。

在扩展中的所有模式都不能包含空白字符,除非空白字符是被转义或引用的。

echo file1,file2\\ :\\ A," B",' C'

file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C

(花括号)匿名函数;代码块与I/O重定向

代码块[花括号]. 这个结构也是一组命令代码块,事实上,它是匿名的函数。然而与一个函数所不同的,在代码块里的变量仍然能被脚本后面的代码访问。

bash$  local a;
	      a=123; 
# bash: local: can only be used in a function
a=123
 a=321; 
echo "a = $a"   # a = 321   (结果是在代码块里的值)

# 多谢, S.C.

由花括号括起的代码块可以引起输入输出的I/O重定向。

例子 3-1. 代码块与I/O重定向

#!/bin/bash
# 从/etc/fstab文件里按一次一行地读.

File=/etc/fstab


read line1
read line2
 < $File

echo "First line in $File is:"
echo "$line1"
echo
echo "Second line in $File is:"
echo "$line2"

exit 0

# 现在,你如何解析每一行的分割符?
# 提示: 使用awk.

例子 3-2. 把一个代码块的结果写进一个文件

  #!/bin/bash
  # rpm-check.sh
  
  # 查询一个rpm安装包的描述,软件清单,和是否它能够被安装.
  # 并把结果保存到一个文件中.
  # 
  # 这个脚本使用一个代码块来举例说明。
  
  SUCCESS=0
  E_NOARGS=65
  
  if [ -z "$1" ]	# 判断第一个参数是否为空
  then
    echo "Usage: `basename $0` rpm-file"	# $0是当前脚本名称
    exit $E_NOARGS
  fi  
  
   
    echo
    echo "Archive Description:"
    rpm -qpi $1       # 查询软件包的描述.
    echo
    echo "Archive Listing:"
    rpm -qpl $1       # 查询软件包中的软件清单.
    echo
    rpm -i --test $1  # 查询该软件包能否被安装.
    if [ "$?" -eq $SUCCESS ]
    then
      echo "$1 can be installed."
    else
      echo "$1 cannot be installed."
    fi  
    echo
   > "$1.test"       # 把代码块的所有输出重定向到一个文件中。
  
  echo "Results of rpm test in file $1.test"
  
  # 参考rpm的man手册来理解上面所用的选项。
  
  exit 0

不像一个用圆括号括起来的命令组,一个用花括号括起的代码块不会以一个子shell运行。[2]

\\;

路径名. 基本上用于find命令里.它不是shell内建的.

分号";"结束find命令中-exec选项的命令序列.它应该转义一下以免被shell误解释。

[]测试表达式

测试.

测试在[]中的表达式. 注意[]是shell内建的测试的一部分(同义于测试),并非 是外部命令/usr/bin/test的链接.

[[]]也是测试表达式

测试.

测试[[]]之中的表达式(shell的关键字).

如:

veg1=carrots
veg2=tomatoes

if [[ "$veg1" < "$veg2" ]]
then
  echo "Although $veg1 precede $veg2 in the dictionary,"
  echo "this implies nothing about my culinary preferences."
else
  echo "What kind of dictionary are you using, anyhow?"
fi

参考[[ … ]]结构的讨论.

[]数组元素.

数组元素.

在数组的上下文中,方括号表示数组的每个元素的数字编号.

Array[1]=slot_1
echo $Array[1]

[]字符集的范围

字符集的范围.

用于正则表达式的一部分,方括号描述一个匹配的字符集范围.

(())整数扩展.

整数扩展.

扩展并计算(( ))里的整数表达式[译者注:粗心的读者要注意了,是整数计算,可不能用来做浮点计算].

参考(( … ))结构的讨论.

> &> >& >> <重定向;进程替换

redirection重定向.

scriptname >filename重定向scriptname的输出到文件filename中去. 如果文件filename存在则将会被覆盖.

command &>filename 会重定向命令command标准输出(stdout)和标准错误(stderr)到文件filename中.

command >&2 把命令command的标准输出(stdout)重定向到标准错误(stderr).

scriptname >>filename appends把脚本scriptname的输出追加到文件filename.如果filename不存在,则它会被创建.

进程替换.

(command)>
<(command)

在不同的上下文中, 字符 "<“和”>"会被当作字符比较操作符.

在另一种不同的上下文中, 字符"<“和”>"被当作整数比较操作符. 请参考例子 12-9.

<<

here document中使用的重定向.

<<<

here string中使用的重定向.

<, >ASCII比较.

ASCII比较.

veg1=carrots
veg2=tomatoes

if [[ "$veg1" < "$veg2" ]]
then
  echo "Although $veg1 precede $veg2 in the dictionary,"
  echo "this implies nothing about my culinary preferences."
else
  echo "What kind of dictionary are you using, anyhow?"
fi

\\<, \\>在 regular expression中的单词界线.(什么意思?)

在 regular expression中的单词界线.

bash$ grep '\\<the\\>' textfile

|管道,把上一个命令的输出传给下一个命令,或shell(上一个进程的标准输出被当成下一个进程命令的标准输入);管道以子进程运行,不能引起父进程变量的改变;管道破坏(broken pipe)SIGPIPE 信号

管道. 把上一个命令的输出传给下一个命令,或是shell. 这是连接命令的一种方法.

echo ls -l | sh
#  把"echo ls -l"的输出传给shell,
#+ 这等同于直接的"ls -l".

cat *.lst | sort | uniq
# 合并且排序所有的".lst"文件,然后删除多余的相同行.

经典的进程间通信方法之一的管道能把一个进程的标准输出发到另一个进程的标准输入.在一种典型的情况,一个命令,比如说cat或echo, 管道传递一个数据流给过滤器(一个改变了它的输入的命令)。

cat $filename1 $filename2 | grep $search_word	# 从文件1和文件2中搜索关键字search_word	

一个命令或一组命令的输出可以由管道传给一个脚本.

#!/bin/bash
# uppercase.sh : 把输入字符改为大写.

tr 'a-z' 'A-Z'
#  字母的范围一定要引号引起来,
#+ 这样才能保护文件名而不会被扩展成单个字母的文件名.

exit 0

现在,让我们把ls -l的输出用管道与这个脚本连起来.

 bash$ ls -l | ./uppercase.sh
 -RW-RW-R--    1 BOZO  BOZO       109 APR  7 19:49 1.TXT
 -RW-RW-R--    1 BOZO  BOZO       109 APR 14 16:48 2.TXT
 -RW-R--R--    1 BOZO  BOZO       725 APR 20 20:56 DATA-FILE

管道里的每一个进程的标准输出都被当成下一个命令的标准输入. 如果不是这种情况,那么数据流会阻塞,并且管道不会引起预期的效果。

cat file1 file2 | ls -l | sort
# 来自"cat file1 file2"的输出会消失.

管道以子进程来运行, 因此不能引起变量的改变。

variable="initial_value"
echo "new_value" | read variable
echo "variable = $variable"     # variable = initial_value

如果在管道中的一个命令失败了,会过早的终结整个管道的执行。这称为管道破坏(broken pipe),这时会发送一个叫SIGPIPE 的信号.

>|强迫重定向

强迫重定向 (即使noclobber选项设置). 这会强迫覆盖一个存在的文件.

||或逻辑操作符(逻辑或)

或逻辑操作符. 在一个测试结构中,||操作符当测试条件的任何一个为真时返回0 (成功)的标志.

&后台运行;

在后台运行作业. 一个后面跟一个&的命令会在后台运行.

 bash$ sleep 10 &
 [1] 850
 [1]+  Done                    sleep 10

在一个脚本里,在后台运行的命令或是偶数的循环可以在后台运行.

例子 3-3. 在后台运行一个循环

#!/bin/bash
# background-loop.sh

for i in 1 2 3 4 5 6 7 8 9 10            # 第一个循环.
do
  echo -n "$i "	# ar:不换行输出
done & # 把这个循环放到后台去.
       # 它有时会后于第二个循环执行.

echo   # 这个'echo'有时不会打印出来.

for i in 11 12 13 14 15 16 17 18 19 20   # 第二个循环.
do
  echo -n "$i "
done  

echo   # 这个'echo'有时不会打印出来.

# ======================================================

# 这个脚本的输出是:
# 1 2 3 4 5 6 7 以上是关于:特殊字符的主要内容,如果未能解决你的问题,请参考以下文章

键盘如何打英文的破折号?

带有特殊字符破折号 (-) 和下划线 (_) 的 Javascript 自定义排序

破折号是R正则表达式中的特殊字符吗?

急求js正则表达式,要求只能输入数字和减号,不能输入其他任何字母或特殊字符,但是减号只能在数字的开

在 ruby​​ 1.8.7 中处理不同类型的 utf 连字符

如何使用带有编解码器值的 python .replace 来删除特殊字符?