上一篇講了 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。