上一篇讲了 zsh 的经常使用字符串操做,这篇开始讲更为琐碎的转义字符和格式化输出相关内容。包括转义字符、引号、print
、printf
的使用等等。其中不少内容没有必要记忆,做为手册参考便可。html
转义字符是不少编程语言中都有的概念,它主要解决某些字符由于没有对应键盘按键没法直接输出、字符自己有特殊含义(好比 \
、"
)或者显示不直观(好比难以区别多个空格和一个 tab)等问题。git
最经常使用的转义字符是 \n
(换行)、\r
(回车)、\t
(tab)。github
直接用 echo
、print
或者 printf
内置命令均可以正常输出转义字符,但包括转义字符的字符串须要用引号(单双引号均可以)扩起来。shell
% echo 'Hello\n\tWorld'
Hello
World复制代码
经常使用转义字符对照表,不经常使用的能够去查 ASCII 码表,而后使用 \xnn
(如 \x14
)。编程
转义字符 | 含义 | ASCII 码值(十六进制) |
---|---|---|
\n | 换行 | 0a |
\r | 回车 | 0d |
\t | tab | 09 |
\\ | \ | 5c |
\` | ` | 60 |
\xnn | 取决于 nn | nn |
能够用 hexdump
命令查看字符的 ASCII 码值。api
% echo ab= | hexdump -C
00000000 61 62 3d 0a |ab=.|
00000004复制代码
还有一些字符是可选转义(一般有特殊含义的字符都是如此)的,好比空格、"
、'
、*
、~
、$
、&
、(
、)
、[
、]
、{
、}
、;
、?
等等,即若是在引号里边则无需转义(即便转义也不出错,转义方法都说前边加一个 \
),但若是在引号外边则须要转义。谨慎起见,包含半角符号的字符串所有用引号包含便可,能够避免没必要要的麻烦。数组
能够这样检查一个字符在空格外是否须要转义,输出的字符中前边带 \
的都是须要的。bash
% str='~!@#$%^&*()_+-={}|[]:;<>?,./"'
# -r 选项表明忽略字符串中的转义符合
# ${(q)str} 功能是为字符串中的特殊符号添加转义符号
% print -r ${(q)str}
\~\!@\#\$%\^\&\*\(\)_+-=\{\}\|\[\]:\;\<\>\?,./\"复制代码
单引号的左右主要是为了不字符串里的特殊字符起做用。在单引号中,只有一个字符须要转义,转义符号 \
。因此若是字符串里包含特殊符号时,最好使用单引号包含起来,避免没必要要的麻烦。若是字符串须要包含单引号,可使用这几种方法。微信
# 用双引号包含
% echo "a'b"
a'b # 用转义符号 % echo a\'b
a'b # 同时使用单引号和转义符号,用于包含单引号和其余特殊符号的场景 % echo 'a"\'\''b*?' a"\'b*?复制代码
双引号的做用相似单引号,但没有单引号那么严格,有些特殊字符在双引号里能够继续起做用。编程语言
# 以使用变量
% str=abc
% echo "$str"
abc
# 可使用 $( ) 运行命令
% echo "$(ls)"
git
tmp
# 可使用 ` ` 运行命令,不建议在脚本里使用 ` `
% echo "`date`"
Mon Aug 28 09:49:11 CST 2017
# 可使用 $(( )) 计算数值
% echo "$(( 1 + 2 ))"
3
# 可使用 $[ ] 计算数值
% echo "$[1 + 2]"
3复制代码
简单说,$
加各类东西的用法在双引号里都是能够正常使用的,而其余特殊符号(好比 *
、?
、>
)的功能一般不可用。
反引号是用来运行命令的,它会返回命令结果,以便保存到变量等等。
% str=`ls`
% echo $str
git
tmp
# 彻底能够用 $( ) 取代
% str=$(ls)
% echo $str
git
tmp复制代码
反引号的功能和 $( )
功能基本同样,但 $( )
能够嵌套,而反引号不能够,并且反引号看起来更费事,某些字体中的反引号和单引号差异不大。因此在脚本里不建议使用反引号。
print
是相似 echo
的内部命令(echo
命令很简单,不做介绍),但功能比 echo
强大不少。彻底可使用 print
代替 echo
。
不加参数的 print
和 echo
的功能基本同样,但若是字符串里包含转义字符,某些状况可能不一致。若是须要输出转义字符,尽可能统一使用 print
,避免不一致致使的麻烦。
% print 'Line\tone\n\Line\ttwo'
Line one
Line two
# echo 的输出和 print 不一致
% echo 'Line\tone\n\Line\ttwo'
Line one
\Line two复制代码
print
有不少参数,在 zsh 里输入 print -
而后按 tab 便可查看选项帮助(若是没有效果,须要配置 ~/.zshrc
里的补全选项,网上有不少现成的配置)。
# - 后直接按 tab,C 是补全上去的
% print -C
-- option --
-C -- print arguments in specified number of columns
-D -- substitute any arguments which are named directories using ~ notation
-N -- print arguments separated and terminated by nulls
...复制代码
这里以经常使用程度的顺序依次介绍全部的选项,另外文末有“print
选项列表”方便查询。
-l
用于分行输出字符串:
# 每一个字符串一行,字符串列表是用空格隔开的
% print -l aa bb
aa
bb
# 也能够接数组,数组相关的内容以后会讲到
# 命令后的多个字符串均可以用数组取代,效果是相同的
% array=(aa bb)
% print -l $array
aa
bb复制代码
-n
用于不在输出内容的末尾自动添加换行符(echo
命令也有这个用法):
% print abc
abc
# 下面输出 abc 后的 % 高亮显示,表明这一行末尾没有换行符
% print -n abc
abc%复制代码
-m
用于只输出匹配到的字符串:
% print -m "aa*" aabb abc aac
aabb aac复制代码
-o/-O/-i
用于对字符串排序:
# print -o 对字符串升序排列
% print -o a d c 1 b g 3 s
1 3 a b c d g s
# print -O 对字符串降序排列
% print -O a d c 1 b g 3 s
s g d c b a 3 1
# 加 -i 参数后,对大小写不敏感
% print -oi A B C a c A B C
A a A B B C c C
# 不加 -i 的话小写排在大写的前面
% print -o A B C a c A B C
a A A B B c C C复制代码
-r
用于不对字符串进行转义。print
默认是会对转义字符进行转义的,加 -r
后会原样输出:
% print -r '\n'
\n复制代码
-c
用于将字符串按列输出。若是对自动决定的列数不满意,能够用 -C
指定列数:
% print -c a bbbbb ccc ddddd ee ffffff gg hhhhhh ii jj kk
a ccc ee gg ii kk
bbbbb ddddd ffffff hhhhhh jj复制代码
-C
用于按指定列数输出字符串:
# 从上到下
% print -C 3 a bb ccc dddd ee f
a ccc ee
bb dddd f
% print -C 3 a bb ccc dddd ee f g
a dddd g
bb ee
ccc f
# 加 -a 后,改为从左向右
% print -a -C 3 a bb ccc dddd ee f g
a bb ccc
dddd ee f
g复制代码
-D
用于将符合条件的路径名转化成带 ~ 的格式(~ 是家目录):
% print -D /home/goreliu/git
~/git
# mine 是这样定义的 hash -d mine='/mnt/c/mine'
% print -D /mnt/c/mine
~mine复制代码
-N
用于将输出的字符串以 \x00
(null)分隔,而不是空格。这样可能方便处理包含空格的字符串,xargs
等命令也能够接受以 \x00
分隔的字符串:
% print -N aa bb cc
aabbcc%
% print -N aa bb cc | hexdump -C
00000000 61 61 00 62 62 00 63 63 00 |aa.bb.cc.|
00000009复制代码
-x
用于将行首的 tab 替换成空格。-x
是将行首的 tab 展开成空格,-x
后的参数是一个 tab 对应的空格数:
% print -x 2 '\t\tabc' | hexdump -C
00000000 20 20 20 20 61 62 63 0a | abc.|
00000008
% print -x 4 '\t\tabc' | hexdump -C
00000000 20 20 20 20 20 20 20 20 61 62 63 0a | abc.|
0000000c复制代码
-X
用于将全部的 tab 补全成空格。注意不是简单地替换成空格。好比每行有一个 tab,-X 8
,那么若是 tab 前(到行首或者上一个 tab)有 5 个字符,就补全 3 个空格,凑够 8,这么作是为了对齐每一列的。但若是前边有 8 个或者 8 个以上字符,那么依然是一个 tab 替换成 8 个字符,由于 tab 不能凭空消失,必定要转成至少一个空格才行。若是没理解就本身多试试找规律吧。
% print -X 2 'ab\t\tabc' | hexdump -C
00000000 61 62 20 20 20 20 61 62 63 0a |ab abc.|
0000000a
% print -X 4 'ab\t\tabc' | hexdump -C
00000000 61 62 20 20 20 20 20 20 61 62 63 0a |ab abc.|
0000000c复制代码
-u
用于指定文件描述符(fd)输出。print
默认输出到 fd 1,即 stdout,能够指定成其余 fd(2 是 stderr,其余的能够运行 ls -l /proc/$$/fd
查看。
% print -u 2 good
good
# 和重定向输出效果同样
% print good >&2复制代码
-v
用于把输出内容保存到变量:
# 和 str="$(print aa bb cc)" 效果同样
% print -v str aa bb cc
% echo $str
aa bb cc复制代码
-s/-S
用于把字符串保存到历史记录:
% print -s ls -a
% history | tail -n 1
2222 ls -a
# -S 也相似,但须要用引号把命令引发来
% print -S "ls -a"
% history | tail -n 1
2339 ls -a复制代码
-z
用于把字符串输出到命令行编辑区:
# _是光标位置
% print -z aa bb cc
% aa bb cc_复制代码
-f
用于按指定格式化字符串输出,同 printf
,用法见“printf
命令用法”。
-P
用于输出带颜色和特殊样式的字符串,见“输出带颜色和特殊样式的字符串”。
-b
用于辨认出 bindkey 中的转义字符串,bindkey 是 Zle 的快捷键配置内容,写脚本用不到,不做介绍。
-R
用于模拟 echo
命令,只支持 -n
和 -e
选项,一般用不到。
printf
命令很像 c 语言的 printf
函数,用于输出格式化后的字符串:
# 末尾输出高亮的 % 表明该行末尾没有换行符
# printf 不会在输出末尾自动添加换行符
# 为了不误解,以后的例子省略该 % 符号
% printf ":%d %f:" 12 34.56
:12 34.560000:%复制代码
printf
的第一个参数是格式化字符串,在 zsh 里输入 printf %
后按 tab,能够看到全部支持的用法。下面只举几个比较经常使用的例子:
# 整数 浮点数 字符串
% printf "%d %f %s" 12 12.34 abcd
12 12.340000 abcd%
# 取小数点后 1 位
% printf "%.1f" 12.34
12.3
# 科学计数法输出浮点数
% printf "%e" 12.34
1.234000e+01
# 将十进制数字转成十六进制输出
% printf "%x" 12
c
# 补齐空格或者补齐 0
% printf "%5d\n%05d" 12 12
12
00012复制代码
我把完整的格式贴在这里,方便搜索:
-- print format specifier --
-- leave one space in front of positive number from signed conversion
- -- left adjust result
. -- precision
' -- thousand separators * -- field width in next argument # -- alternate form % -- a percent sign + -- always place sign before a number from signed conversion 0 -- zero pad to length b -- as %s but interpret escape sequences in argument c -- print the first character of the argument E e -- double number in scientific notation f -- double number G g -- double number as %f or %e depending on size i d -- signed decimal number or with leading " numeric value of following character n -- store number of printed bytes in parameter specified by argument o -- unsigned octal number q -- as %s but shell quote result s -- print the argument as a string u -- unsigned decimal number X x -- unsigned hexadecimal number, letters capitalized as x复制代码
用 zsh 的 print -P
能够方便地输出带颜色和特殊样式的字符串,不用再和 \033[41;36;1m
之类莫名其妙的字符串打交道了。
# %B 加粗 %b 取消加粗
# %F{red} 前景色 %f 取消前景色
# %K{red} 背景色 %k 取消背景色
# %U 下滑线 %u 取消下滑线
# %S 反色 %s 取消反色
#
# black or 0 red or 1
# green or 2 yellow or 3
# blue or 4 magenta or 5
# cyan or 6 white or 7
# 显示加粗的红色 abc
% print -P '%B%F{red}abc'
abc
# 没覆盖到的功能能够用原始的转义符号,可读性比较差
# 4[0-7] 背景色
# 3[0-7] 前景色
# 0m 正常 1m 加粗 2m 变灰 3m 斜体 4m 下滑钱 5m 闪烁 6m 快速闪烁 7m 反色
# 显示闪烁的红底绿字 abc
% print "\033[41;32;5mabc\033[0m"
abc复制代码
为了方便查询,我把 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 | 把内容放置到命令行编辑区 | 无 |
zsh.sourceforge.net/Guide/zshgu…
全系列文章地址:github.com/goreliu/zsh…
付费解决 Windows、Linux、Shell、C、C++、AHK、Python、JavaScript、Lua 等领域相关问题,灵活订价,欢迎咨询,微信 ly50247。