Shell
格式化輸出:下劃線
我編寫了以下函式,
ksh
它將它的第一個參數列印到螢幕上,並用適當數量的-
字元為它加下劃線:print_underlined () { word=$1 echo $word i=${#word} while [[ i -gt 0 ]]; do printf "-" (( i = $i - 1 )) done printf "\n" }
例子:
$ print_underlined foobar foobar ------ $
我想知道是否有一種更簡單、更優雅的方式來在螢幕上顯示帶下劃線的單詞。
對於我正在使用的記錄:
- 索拉里斯 10
- ksh88
您問題的核心是建構一個完全由下劃線組成的字元串,其長度與現有字元串的長度相同。在最近足夠多的 bash、ksh 或 zsh 版本中,您可以使用以下構造建構此字元串
${VARIABLE//PATTERN/REPLACEMENT}
:underlines=${word//?/_}
。但是這個結構在 ksh88 中不存在。在任何 shell 中,您都可以使用
tr
。POSIX 兼容的實現tr
讓您可以編寫以下程式碼:underlines=$(printf %s "$word" | tr -c '_' '[_*]')
我認為 Solaris 10 預設具有 POSIX 兼容
tr
,但可能有一個歷史實現(與早期的 Solaris 版本兼容)。的歷史實現tr
可能不理解[x*]
語法,但他們傾向於接受以下語法(POSIX 不保證),意思是“用 替換所有不是換行符的內容_
”:underlines=$(echo "$word" | tr -c '\010' '_') underlines=${underlines%_}
這是一個有點瘋狂的方法,它不使用任何循環或外部程序,並且應該在任何 Bourne shell 中工作(至少自從
set -f
引入以來——儘管在空目錄中執行會減輕缺少set -f
. 不幸的是,它僅在字元串不包含任何空格時才有效。set -f # turn off globbing IFS=$word # split at any character in $word set a $word # split $word into one word between each character, i.e. empty words shift # remove the leading a (needed in case $word starts with -) IFS=_ underlines=$* # join the empty words, separated with the new value of $IFS
一個更複雜的變體處理空白,但前提是沒有任何連續的空白序列。我不認為你可以用這個技巧走得更遠,因為其中的空白字元序列
IFS
總是折疊的。set -f unset IFS; set a $0 # split at whitespace IFS=$*; set $* # split into empty words IFS=_; underlines=$* # collect the empty