作者|陌辞寒

导读

上一篇讲了 zsh 的常用字符串操作,这篇开始讲更为琐碎的转义字符和格式化输出相关内容。包括转义字符、引号、print、printf的使用等等。其中很多内容没有必要记忆,作为手册参考即可。

转义字符

转义字符是很多编程语言中都有的概念,它主要解决某些字符因为没有对应键盘按键无法直接输出、字符本身有特殊含义(比如、”)或者显示不直观(比如难以区别多个空格和一个 tab)等问题。

最常用的转义字符是n(换行)、r(回车)、t(tab)。

直接用echo、print或者printf内置命令都可以正常输出转义字符,但包括转义字符的字符串需要用引号(单双引号都可以)扩起来。

  1. % echo 'HellontWorld'

  2. Hello

  3.        World

常用转义字符对照表,不常用的可以去查 ASCII 码表,然后使用xnn(如x14)。

转义字符含义ASCII 码值(十六进制)

n

换行

0a

r

回车

0d

t

tab

09

\

5c

`

`

60

xnn

取决于 nn

nn

可以用hexdump命令查看字符的 ASCII 码值。

  1. % echo ab= | hexdump -C

  2. 00000000  61 62 3d 0a                                       |ab=.|

  3. 00000004

还有一些字符是可选转义(通常有特殊含义的字符都是如此)的,比如空格、”、’、*、~、$、&、(、)、[、]、{、}、;、?等等,即如果在引号里边则无需转义(即使转义也不出错,转义方法都说前边加一个),但如果在引号外边则需要转义。谨慎起见,包含半角符号的字符串全部用引号包含即可,可以避免不必要的麻烦。

可以这样检查一个字符在空格外是否需要转义,输出的字符中前边带的都是需要的。

  1. % str='~!@#$%^&*()_+-={}|[]:;?,./"'

  2. # -r 选项代表忽略字符串中的转义符合

  3. # ${(q)str} 功能是为字符串中的特殊符号添加转义符号

  4. % print -r ${(q)str}

  5. ~!@#$%^&*()_+-={}|[]:;?,./"

单引号

单引号的左右主要是为了避免字符串里的特殊字符起作用。在单引号中html转义字符,只有一个字符需要转义,转义符号。所以如果字符串里包含特殊符号时,最好使用单引号包含起来,避免不必要的麻烦。如果字符串需要包含单引号,可以使用这几种方法。

  1. # 用双引号包含

  2. % echo "a'b"

  3. a'b

  4. # 用转义符号

  5. % echo a'b

  6. a'b

  7. # 同时使用单引号和转义符号,用于包含单引号和其他特殊符号的场景

  8. % echo 'a"'''b*?'

  9. a"'b*?

双引号

双引号的作用类似单引号,但没有单引号那么严格,有些特殊字符在双引号里可以继续起作用。

  1. # 以使用变量

  2. % str=abc

  3. % echo "$str"

  4. abc

  5. # 可以使用 $( ) 运行命令

  6. % echo "$(ls)"

  7. git

  8. tmp

  9. # 可以使用 ` ` 运行命令,不建议在脚本里使用 ` `

  10. % echo "`date`"

  11. Mon Aug 28 09:49:11 CST 2017

  12. # 可以使用 $(( )) 计算数值

  13. % echo "$(( 1 + 2 ))"

  14. 3

  15. # 可以使用 $[ ] 计算数值

  16. % echo "$[1 + 2]"

  17. 3

简单说,$加各种东西的用法在双引号里都是可以正常使用的,而其他特殊符号(比如*、?、>)的功能通常不可用。

反引号

反引号是用来运行命令的,它会返回命令结果,以便保存到变量等等。

  1. % str=`ls`

  2. % echo $str

  3. git

  4. tmp

  5. # 完全可以用 $( ) 取代

  6. % str=$(ls)

  7. % echo $str

  8. git

  9. tmp

反引号的功能和$( )功能基本一样,但$( )可以嵌套,而反引号不可以,而且反引号看起来更费事,某些字体中的反引号和单引号差别不大。所以在脚本里不建议使用反引号。

print 命令用法

print是类似echo的内部命令(echo命令很简单,不作介绍),但功能比echo强大很多。完全可以使用print代替echo。

不加参数的print和echo的功能基本一样,但如果字符串里包含转义字符,某些情况可能不一致。如果需要输出转义字符,尽量统一使用print,避免不一致导致的麻烦。

  1. % print 'LinetonenLinettwo'

  2. Line    one

  3. Line    two

  4. # echo 的输出和 print 不一致

  5. % echo 'LinetonenLinettwo'

  6. Line    one

  7. Line   two

print有很多参数,在 zsh 里输入print -然后按 tab 即可查看选项帮助(如果没有效果,需要配置~/.zshrc里的补全选项,网上有很多现成的配置)。

  1. # - 后直接按 tabC 是补全上去的

  2. % print -C

  3. -- option --

  4. -C  -- print arguments in specified number of columns

  5. -D  -- substitute any arguments which are named directories using ~ notation

  6. -N  -- print arguments separated and terminated by nulls

  7. ...

print 命令选项功能介绍

这里以常用程度的顺序依次介绍所有的选项html转义字符,另外文末有“print选项列表”方便查询。

-l用于分行输出字符串:

  1. # 每个字符串一行,字符串列表是用空格隔开的

  2. % print -l aa bb

  3. aa

  4. bb

  5. # 也可以接数组,数组相关的内容之后会讲到

  6. # 命令后的多个字符串都可以用数组取代,效果是相同的

  7. % array=(aa bb)

  8. % print -l $array

  9. aa

  10. bb

-n用于不在输出内容的末尾自动添加换行符(echo命令也有这个用法):

  1. % print abc

  2. abc

  3. # 下面输出 abc 后的 % 高亮显示,代表这一行末尾没有换行符

  4. % print -n abc

  5. abc%

-m用于只输出匹配到的字符串:

  1. % print -m "aa*" aabb abc aac

  2. aabb aac

-o/-O/-i用于对字符串排序:

  1. # print -o 对字符串升序排列

  2. % print -o a d c 1 b g 3 s

  3. 1 3 a b c d g s

  4. # print -O 对字符串降序排列

  5. % print -O a d c 1 b g 3 s

  6. s g d c b a 3 1

  7. # -i 参数后,对大小写不敏感

  8. % print -oi A B C a c A B C

  9. A a A B B C c C

  10. # 不加 -i 的话小写排在大写的前面

  11. % print -o A B C a c A B C

  12. a A A B B c C C

-r用于不对字符串进行转义。print默认是会对转义字符进行转义的,加-r后会原样输出:

  1. % print -r 'n'

  2. n

-c用于将字符串按列输出。如果对自动决定的列数不满意,可以用-C指定列数:

  1. % print -c a bbbbb ccc ddddd ee ffffff gg hhhhhh ii jj kk

  2. a       ccc     ee      gg      ii      kk

  3. bbbbb   ddddd   ffffff  hhhhhh  jj

-C用于按指定列数输出字符串:

  1. # 从上到下

  2. % print -C 3 a bb ccc dddd ee f

  3. a     ccc   ee

  4. bb    dddd  f

  5. % print -C 3 a bb ccc dddd ee f g

  6. a     dddd  g

  7. bb    ee

  8. ccc   f

  9. # -a 后,改成从左向右

  10. % print -a -C 3 a bb ccc dddd ee f g

  11. a     bb    ccc

  12. dddd  ee    f

  13. g

-D用于将符合条件的路径名转化成带 ~ 的格式(~ 是家目录):

  1. % print -D /home/goreliu/git

  2. ~/git

  3. # mine 是这样定义的 hash -d mine='/mnt/c/mine'

  4. % print -D /mnt/c/mine

  5. ~mine

-N用于将输出的字符串以x00(null)分隔,而不是空格。这样可能方便处理包含空格的字符串,xargs等命令也可以接受以x00分隔的字符串:

  1. % print -N aa bb cc

  2. aabbcc%

  3. % print -N aa bb cc | hexdump -C

  4. 00000000  61 61 00 62 62 00 63 63  00                       |aa.bb.cc.|

  5. 00000009

-x用于将行首的 tab 替换成空格。-x是将行首的 tab 展开成空格,-x后的参数是一个 tab 对应的空格数:

  1. % print -x 2 'ttabc' | hexdump -C

  2. 00000000  20 20 20 20 61 62 63 0a                           |    abc.|

  3. 00000008

  4. % print -x 4 'ttabc' | hexdump -C

  5. 00000000  20 20 20 20 20 20 20 20  61 62 63 0a              |        abc.|

  6. 0000000c

-X用于将所有的 tab 补全成空格。注意不是简单地替换成空格。比如每行有一个 tab,-X 8,那么如果 tab 前(到行首或者上一个 tab)有 5 个字符,就补全 3 个空格,凑够 8,这么做是为了对齐每一列的。但如果前边有 8 个或者 8 个以上字符,那么依然是一个 tab 替换成 8 个字符,因为 tab 不能凭空消失,一定要转成至少一个空格才行。如果没理解就自己多试试找规律吧。

  1. % print -X 2 'abttabc' | hexdump -C

  2. 00000000  61 62 20 20 20 20 61 62  63 0a                    |ab    abc.|

  3. 0000000a

  4. % print -X 4 'abttabc' | hexdump -C

  5. 00000000  61 62 20 20 20 20 20 20  61 62 63 0a              |ab      abc.|

  6. 0000000c

-u用于指定文件描述符(fd)输出。print默认输出到 fd 1,即 stdout,可以指定成其他 fd(2 是 stderr,其他的可以运行ls -l /proc/$$/fd查看。

  1. % print -u 2 good

  2. good

  3. # 和重定向输出效果一样

  4. % print good >&2

-v用于把输出内容保存到变量:

  1. # str="$(print aa bb cc)" 效果一样

  2. % print -v str aa bb cc

  3. % echo $str

  4. aa bb cc

-s/-S用于把字符串保存到历史记录:

  1. % print -s ls -a

  2. % history | tail -n 1

  3. 2222  ls -a

  4. # -S 也类似,但需要用引号把命令引起来

  5. % print -S "ls -a"

  6. % history | tail -n 1

  7. 2339  ls -a

-z用于把字符串输出到命令行编辑区:

  1. # _是光标位置

  2. % print -z aa bb cc

  3. % aa bb cc_

-f用于按指定格式化字符串输出,同printf,用法见“printf命令用法”。

-P用于输出带颜色和特殊样式的字符串,见“输出带颜色和特殊样式的字符串”。

-b用于辨认出 bindkey 中的转义字符串,bindkey 是 Zle 的快捷键配置内容,写脚本用不到,不作介绍。

-R用于模拟echo命令,只支持-n和-e选项,通常用不到。

printf 命令用法

printf命令很像 c 语言的printf函数,用于输出格式化后的字符串:

  1. # 末尾输出高亮的 % 代表该行末尾没有换行符

  2. # printf 不会在输出末尾自动添加换行符

  3. # 为了避免误解,之后的例子省略该 % 符号

  4. % printf ":%d %f:" 12 34.56

  5. :12 34.560000:%

printf的第一个参数是格式化字符串,在 zsh 里输入printf %后按 tab,可以看到所有支持的用法。下面只举几个比较常用的例子:

  1. # 整数 浮点数 字符串

  2. % printf "%d %f %s" 12 12.34 abcd

  3. 12 12.340000 abcd%

  4. # 取小数点后 1

  5. % printf "%.1f" 12.34

  6. 12.3

  7. # 科学计数法输出浮点数

  8. % printf "%e" 12.34

  9. 1.234000e+01

  10. # 将十进制数字转成十六进制输出

  11. % printf "%x" 12

  12. c

  13. # 补齐空格或者补齐 0

  14. % printf "%5dnd" 12 12

  15.   12

  16. 00012

我把完整的格式贴在这里,方便搜索:

  1. -- print format specifier --

  2.      -- leave one space in front of positive number from signed conversion

  3. -     -- left adjust result

  4. .     -- precision

  5. '     -- thousand separators

  6. *     -- field width in next argument

  7. #     -- alternate form

  8. %     -- a percent sign

  9. +     -- always place sign before a number from signed conversion

  10. 0     -- zero pad to length

  11. b     -- as %s but interpret escape sequences in argument

  12. c     -- print the first character of the argument

  13. E  e  -- double number in scientific notation

  14. f     -- double number

  15. G  g  -- double number as %f or %e depending on size

  16. i  d  -- signed decimal number or with leading " numeric value of following character

  17. n     -- store number of printed bytes in parameter specified by argument

  18. o     -- unsigned octal number

  19. q     -- as %s but shell quote result

  20. s     -- print the argument as a string

  21. u     -- unsigned decimal number

  22. X  x  -- unsigned hexadecimal number, letters capitalized as x

输出带颜色和特殊样式的字符串

用 zsh 的print -P可以方便地输出带颜色和特殊样式的字符串,不用再和33[41;36;1m之类莫名其妙的字符串打交道了。

  1. # %B 加粗 %b 取消加粗

  2. # %F{red} 前景色 %f 取消前景色

  3. # %K{red} 背景色 %k 取消背景色

  4. # %U 下滑线 %u 取消下滑线

  5. # %S 反色 %s 取消反色

  6. #

  7. # black or 0  red     or 1

  8. # green or 2  yellow  or 3

  9. # blue  or 4  magenta or 5

  10. # cyan  or 6  white   or 7

  11. # 显示加粗的红色 abc

  12. % print -P '%B%F{red}abc'

  13. abc

  14. # 没覆盖到的功能可以用原始的转义符号,可读性比较差

  15. # 4[0-7] 背景色

  16. # 3[0-7] 前景色

  17. # 0m 正常 1m 加粗 2m 变灰 3m 斜体 4m 下滑钱 5m 闪烁 6m 快速闪烁 7m 反色

  18. # 显示闪烁的红底绿字 abc

  19. % print "33[41;32;5mabc33[0m"

  20. abc

print 选项列表

为了方便查询,我把print的选项列表放在这里:

选项功能参数

-C

按列输出

列数

-D

替换路径成带~的版本

-N

使用x00作为字符串的间隔

-O

降序排列

-P

输出颜色和特殊样式

-R

模拟echo命令

-S

放命令放入历史命令文件(要加引号)

-X

替换所有 tab 为空格

tab 对应空格数

-a

和-c/-C一起使用时,改为从左到右

-b

识别出 bindkey 转义字符串

-c

按列输出(自动决定列数)

-f

同printf

-i

和-o/-O一起用时,大小写不敏感排序

-l

使用换行符作为字符串分隔符

-m

只输出匹配的字符串

匹配模式字符串

-n

不自动添加最后的换行符

-o

升序排列

-r

不处理转义字符

-s

放命令放入历史命令文件(不加引号)

-u

指定 fd 输出

fd 号

-v

把内容保存到变量

变量名

-x

替换行首的 tab 为空格

tab 对应空格数

-z

把内容放置到命令行编辑区

参考

限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688