ソースコード内のread -pのプロンプトで長い文字列を複数の行に分割する方法は?


18

として実行されるインストールスクリプトを作成しています/bin/sh

ファイルの入力を求める行があります:

read -p "goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n] " REPLY

この長い行を多くの行に分割して、80文字を超えないようにします。スクリプトのソースコード内の行について話しています。スクリプトの実行時に画面に実際に印刷される行についてではありません

私が試したもの:

  • フリストアプローチ:

    read -p "goat can try change directory if cd fails to do so. " \
        "Would you like to add this feature? [Y|n] " REPLY
    

    印刷しないので、これは機能しませんWould you like to add this feature? [Y|n]

  • 2番目のアプローチ:

    echo "goat can try change directory if cd fails to do so. " \
        "Would you like to add this feature? [Y|n] "
    read REPLY

    うまくいきません。プロンプトの後に改行を出力します。に-nオプションを追加しechoても役に立たない:ただ印刷する:

    -n goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n]
    # empty line here
  • 私の現在の回避策は

    printf '%s %s ' \
        "goat can try change directory if cd fails to do so." \
        "Would you like to add this feature? [Y|n] "
    read REPLY

そして、もっと良い方法があるのだろうか。

/bin/sh互換性のあるソリューションを探していることを忘れないでください。


1
より広い端末および/またはエディタウィンドウを使用することをお勧めします(たとえば、1440pモニターで192列x 51行の端末を使用します-ログファイルのテーリングやvimでのソースコードの編集に最適です)。時々ソースコードの行が80文字より長くなるという事実-それは避けられません。小さいフォントを使用すると、さらに幅の広い端末を使用できますが、現在の設定は幅と読みやすさのバランスが取れています。
cas

回答:


16

まず、変数を使用してテキスト行から読み取りを分離します。

text="line-1 line-2"             ### Just an example.
read -p "$text" REPLY

このようにして、問題は次のようになります。変数に2行を割り当てる方法。

もちろん、それを行う最初の試みは次のとおりです。

a="line-1 \
line-2"

そのように書かれて、varはa実際にvalueを取得しますline-1 line-2

しかし、これによって作成されるインデントの欠如は気に入らないでしょう。それでは、here-docからvarに行を読み取ろうとするかもしれません(here-doc内のインデントされた行にはスペースではなくタブが必要です。正しく動作するように):

    a="$(cat <<-_set_a_variable_
        line-1
        line-2
        _set_a_variable_
    )"
echo "test1 <$a>"

しかし、実際には2行が書き込まれるので失敗し$aます。1行のみを取得する回避策は次のとおりです。

    a="$( echo $(cat <<-_set_a_variable_
        line 1
        line 2
        _set_a_variable_
        ) )"
echo "test2 <$a>"

それは近いですが、他の追加の問題を作成します。

正しい解決策。

上記のすべての試みは、この問題をより複雑にします。

非常に基本的でシンプルなアプローチは次のとおりです。

a="line-1"
a="$a line-2"
read -p "$a" REPLY

特定の例のコードは次のとおりです(readサポートするシェルの場合-p)。

#!/bin/dash
    a="goat can try change directory if cd fails to do so."
    a="$a Would you like to add this feature? [Y|n] "
# absolute freedom to indent as you see fit.
        read -p "$a" REPLY

他のすべてのシェルでは、次を使用します。

#!/bin/dash
    a="goat can try change directory if cd fails to do so."
    a="$a Would you like to add this feature? [Y|n] "
# absolute freedom to indent as you see fit.
        printf '%s' "$a"; read REPLY

@BinaryZebra私は知っています。すべてのシェルが読み取ったわけではなく、すべてのシェルが-pを持っているわけではないので、「for any shell」を修正しました。
テルドン

@terdon私たちは両方とも同意していますそれが感謝の理由です:-)。再度、感謝します。

1

行末のバックスラッシュは、出力の実際の改行ではなく、複数行にわたるコマンドの継続を許可します。

たとえば、最初のアプローチはコマンドになります

read -p "goat can try change directory if cd fails to do so. " "Would you like to add this feature? [Y|n] " REPLY

なぜ複数行を出力するように読みたいのか分かりませんが、単にreadプロンプト行とechoその前の行に使用します。

コードを複数行にわたって読みやすくするには、行間で引用符を閉じたり開いたりしないでください。

これを試して:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY

2行印刷しないようにします。スクリプトのソースコードのコードを 1行あたり80文字に収めたいだけです。答えてくれてありがとう:)
マテウスピオトロフスキ

インデントがないため、あなたが提案したアプローチは好きではありません。私readが関数内でインデントされている場合、あなたのアプローチは読みやすさを台無しにしているようです。
マテウスピオトロフスキ

1

変数を使用する@BinaryZebraのアプローチはよりクリーンであることがわかりますが、あなたが試みた方法でそれを行うこともできます。引用符の中に改行を入れるだけです:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY

すべての行の後に改行を追加すると読みやすくなると思いますか?\nプロンプトに挿入する方法を探していなかったからです。私は破るために望んでいたコードを、すべての行が80文字以下であるように、複数の行に。
マテウスピオトロフスキ

1
@MateuszPiotrowskiああ、それははるかに理にかなっています。その場合、私の答えはあまり役に立ちません。質問を編集して、出力ではなくコードを分割することを明確にしてください。私は今モバイルにいますが、明日何かを思いつくことができるかどうかを確認します。
テルドン

1
@MateuszPiotrowski完了、元々試していたものの作業バージョンを追加しました。
テルドン

0

これはどうですか:

#!/ bin / bash
read -p "こんにちは
世界
これは
複数行
プロンプト:」プロンプト
echo $ PROMPT


どのようにインデントしますか?
マテウスピオトロ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.