フォーマットされた出力:下線

フォーマットされた出力:下線

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
  • クッシュ 88

答え1

問題の鍵は、既存の文字列と同じ長さのアンダースコアで構成される文字列を構築することです。最新バージョンのbash、ksh、またはzshでは、次の構文を使用してこの文字列を作成できます${VARIABLE//PATTERN/REPLACEMENT}underlines=${word//?/_}ただし、この構成はksh88には存在しません。

すべてのシェルで使用できます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シェルで動作する少し狂った方法です(少なくとも導入後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

答え2

最新のシェルでは、次のことができますprintf %s\\n "${word//?/-}"。私はksh88に特別な拡張子がないと思います。

追加のプロセスが気に入らない場合は、これを行うことができますprintf %s\\n "${word}" | sed -e 's/./-/g'

あなたのアプローチも素晴らしいですが、次のように少し変更します。

print_underlined () {
        word=$1
        printf %s\\n "$word"
        i=${#word}
        while (( i )); do
                printf -
                (( i = i - 1 ))
        done
        echo
}

まったく異なるアプローチを使用するには、端末の機能を使用して実際の下線を表示します(使用可能な場合)。

tput smul; printf %s\\n "$word"; tput rmul

もちろん、これはスクリプトが実行されている端末がそれをサポートしているかどうかを知っている場合にのみ機能します。

答え3

私は単にインターネット検索でこれを見つけました。

underline() { echo $1; echo "${1//?/${2:--}}";}

基本的には同じですが、よりコンパクトです。混乱している場合は、支柱の交換に関する詳細情報をご覧ください。ここ。 sed 構文によく似ています。

答え4

これは、Solaris 10およびksh88で動作するPOSIX互換方式です。

print_underlined () {
  printf "%s\n%s\n" "$1" $(printf "%s\n" "$1" | sed "s/./-/g")
}

$ print_underlined "hello world"
hello world
-----------

関連情報