bash コマンド置換に引数の長さを渡す

bash コマンド置換に引数の長さを渡す

README.md私はaを$1\n下線の長さで埋める高速bash関数を書こうとしています$1

他のstackexchange質問で見つかったコードは、文字の<n>時間を印刷するために次のように使用されています。

printf '=%.0s' {1..<n>}

実際、これはうまくいきます(明らかに<n>数字を代わりに使用します)。

鉱山を作るには、README.md関数は次のようになると思いました。

make_readme() {
    echo "$1
$(printf '=%.0s' {1..${#1}})" > README.md
}

make_readme "Some project"

ただし、これにより、次のテキストを含むファイルが生成されます。

Some project
=

私が知る限り、${#1}inは$(...)空の文字列に置き換えられます。私の意見では、コマンド置換には独自のパラメータ範囲があり、パラメータが置換に渡されないため、$1何も置き換えられないようです。

ついにいくつかの解決策が見つかりました。

make_readme() {
    underline="printf '=%.0s' {1..${#1}}"
    echo "$1
$(eval "$underline")" > README.md
}

または

make_readme() {
    echo "$1" > README.md
    printf '=%.0s' {1..${#1}} >> README.md
}

しかし、これを一行で実行する方法があるはずです。

答え1

提案:

#!/bin/bash

make_readme () {
    printf '%s\n%s\n' "$1" "$( eval "printf '=%.0s' {1..${#1}}" )"
}

make_readme 'Hello World!' >README.md

または外部ユーティリティ呼び出しが機能している場合

#!/bin/bash

make_readme () {
    # print $1, then replace all characters in it with = and print again
    sed 'p; s/./=/g' <<<"$1"
}

make_readme 'Hello World!' >README.md

どちらもREADME.mdインクルードというファイルを生成します。

Hello World!
============

答え2

私は以下をお勧めします:

make_readme () {
    printf '%s\n%s\n' "$1" "${1//?/=}"
}

make_readme 'Hello World!' >README.md

答え3

あなたのため実際の問題これは「与えられた文字列を生成します。同じ長さ=文字列変更された他の答えに同意します。ひもbash、zsh、tr、sedなどを使用してください。

しかし、あなたのために指定された問題これは「与えられた数字その長さの文字列を生成します。${#1} 後ろにサポート拡張リファレンス;シェル拡張によるマニュアルまたは情報

あなたのためのいくつかの方法がありますできる与えられた長さの文字列を生成します。

  1. あなたの%.0sスキルを使うプログラム seq中括弧拡張の代わりに(コマンド置換が最初に実行されるサブシェルを作成し、パラメータ拡張を実行するため):
    printf '%s\n' "$1"; printf '=%.0s' $( seq ${#1} ); printf '\n'
  1. 「可変幅」形式を使用してパディングを作成してprintf修正します。
    # create a string of spaces equal to length of $1, then convert spaces to =
    t=$(printf '%*s' ${#1} ''); printf '%s\n' "$1" "${t// /=}"

    # create a string of zeros equal to length of $1, then convert zeros to =
    t=$(printf '%0*d' ${#1} 0); printf '%s\n' "$1" "${t//0/=}"
  1. 今日のシステムでは一般的ですが、POSIXでは一般的ではないPerlの使用:
    printf '%s\n' "$1" "$( perl -e "print '='x${#1}" )"
    # quoting $(perl...) isn't needed when we know (all) the chars are =
    # but is good practice in general
    # note I reverse the more common method of singlequoting a perl script
    # with internal strings doublequoted, because I _want_ shell expansion

答え4

bashシェルを使用する必要がない場合は、zsh代わりに次のようにします。

make_readme() printf '%s\n' $1 ${(l[$#1][=])}

左側のパディングパラメータ拡張フラグはどこにあります(l[length][string])(ここではパラメータはまったく適用されません)。

各文字の表示幅が考慮されるため、幅がゼロまたは幅が2つの文字を含むテキストでうまく機能します。

$ make_readme() printf '%s\n' $1 ${(l[$#1*3-${#${(ml:$#1*2:)1}}][=])}
$ make_readme $'Ste\u0301phane'
Stéphane
========
$ make_readme 'FOOBAR'
FOOBAR
============

(これはU + FF21..U + FF3A二重幅アルファベットです。ブラウザではこれを全二重幅として表示しない可能性がありますが、端末では表示する必要があります。)

${(ml:width:)1}パディングは$1width文字の表示幅を考慮しているため、文字数の2倍にパディングするときに$1文字数と文字数$1を比較して表示幅を計算できます。バラより文字列の表示幅を取得します。もっと学ぶ。

関連情報