590

Rails プロジェクトの国際化のために YAML 辞書を作成しようとしています。ただし、一部のファイルでは文字列が二重引用符で囲まれている場合とない場合があるため、少し混乱しています。考慮すべきいくつかの点:

  • 例 1 - すべての文字列で二重引用符を使用します。
  • 例 2 - 文字列 (最後の 2 つを除く) は引用符を使用しません。
  • YAML クックブックには次のように書かれています。文字列を二重引用符で囲むと、エスケープを使用して ASCII および Unicode 文字を表すことができます。これは、一部の文字をエスケープしたい場合にのみ二重引用符を使用する必要があるということですか? はいの場合-最初の例でどこでも二重引用符を使用するのはなぜですか-統一/文体上の理由のためだけですか?
  • 例 2 の最後の 2 行で!は非固有のタグが使用されていますが、最初の例の最後の 2 行では使用されていません。どちらも機能します。

私の質問は、YAML でさまざまな種類の引用符を使用するためのルールは何ですか?

次のように言えますか。

  • 通常、引用符は必要ありません。
  • 文字をエスケープしたい場合は、二重引用符を使用してください。
  • !... ?!? の場合、一重引用符とともに使用します。
4

7 に答える 7

803

質問で引用されている YAML クックブックの簡単なレビューといくつかのテストの後、ここに私の解釈があります。

  • 通常、引用符は必要ありません。
  • 引用符を使用して文字列を強制します。たとえば、キーまたは値が である10が、Fixnum ではなく文字列を返したい場合は、 or を記述し'10'ます"10"
  • 値に特殊文字が含まれる場合は引用符を使用します(例: :, {, }, [, ], ,, &, *, #, ?, |, -, <, >) 。=!%@\
  • 一重引用符を使用すると、ほとんどすべての文字を文字列に入れることができ、エスケープ コードを解析しようとしません。'\n'文字列として返されます\n
  • 二重引用符はエスケープ コードを解析します。 "\n"改行文字として返されます。
  • 感嘆符は!ruby/sym、Ruby シンボルを返すなどのメソッドを導入します。

最善の方法は、必要でない限り引用符を使用しないことであり、特にエスケープ コードを処理する必要がない限り、単一引用符を使用することです。

アップデート

「はい」と「いいえ」は引用符 (一重または二重) で囲む必要があります。そうしないと、TrueClass および FalseClass の値として解釈されます。

en:
  yesno:
    'yes': 'Yes'
    'no': 'No'
于 2014-03-06T20:19:37.513 に答える
20

この質問に対する素晴らしい回答がいくつかあります。ただし、それらを拡張し、 YAMLを考慮したすべてのものの「真のソース」である新しい公式の YAML v1.2.2 仕様(2021 年 10 月 1 日リリース) からいくつかのコンテキストを提供したいと思います。

文字列を表すために使用できる 3 つの異なるスタイルがあり、それぞれに独自の (欠点) 利点があります。

YAML は、二重引用符、単一引用符、およびプレーン (引用符なし) の 3 つのフロー スカラー スタイルを提供します。それぞれが、読みやすさと表現力の間で異なるトレードオフを提供します。

二重引用符のスタイル:

  • 二重引用符で囲まれたスタイルは、周囲の"インジケーターによって指定されます。\これは、エスケープ シーケンスを使用して任意の文字列を表現できる唯一のスタイルです。\これには、文字と文字をエスケープする必要があり"ます。

単一引用符のスタイル:

  • 単一引用符で囲まれたスタイルは、周囲の'インジケーターによって指定されます。したがって、単一引用符で囲まれたスカラー内では、そのような文字を繰り返す必要があります。これは、単一引用符で囲まれたスカラーで実行される唯一のエスケープ形式です。特に\"文字は自由に使用できます。これにより、単一引用符で囲まれたスカラーが印刷可能な文字に制限されます。さらに、空白文字が非空白文字で囲まれている長い一重引用符で囲まれた行のみを分割することができます。

プレーン (引用符なし) スタイル:

  • プレーン (引用符なし) のスタイルには識別インジケーターがなく、エスケープの形式もありません。したがって、これは最も読みやすく、最も限定的で、最もコンテキストに依存するスタイルです。制限された文字セットに加えて、プレーン スカラーを空にしたり、先頭または末尾に空白文字を含めたりすることはできません。スペース文字が非スペースで囲まれている長いプレーン行のみを分割することができます。プレーンなスカラーは、ほとんどのインジケーターで開始してはなりません。これは、他の YAML コンストラクトとあいまいさを引き起こす可能性があるためです。ただし、スペース以外の「安全な」文字が続く場合は、あいまいさが生じないため、 :,?およびインジケータを最初の文字として使用できます。-

TL;DR

そうは言っても、公式の YAML 仕様によると、次のようにする必要があります。

  • 最も読みやすいので、該当する場合はいつでも引用符なしのスタイルを使用してください。
  • やなどの文字が文字列内で使用されている場合は、単一引用符で囲んだスタイル ( ')を使用して、エスケープを回避し、読みやすさを向上させます。"\
  • "最初の 2 つのオプションでは不十分な場合、つまり、より複雑な改行が必要な場合や印刷できない文字が必要な場合は、二重引用符で囲んだスタイル ( ) を使用します。
于 2021-11-05T08:51:11.317 に答える
0

必要に応じて文字列を一重引用符で囲み、結果を元の値にアンマーシャリングできるかどうかをテストする小さな関数 (パフォーマンスのために最適化されていません) を次に示します: https://go.dev/play/p/AKBzDpVz9hk。ルールをテストする代わりに、マーシャラー自体を使用して、マーシャリングおよびアンマーシャリングされた値が元のバージョンと一致するかどうかを確認します。

func yamlQuote(value string) string {
    input := fmt.Sprintf("key: %s", value)

    var res struct {
        Value string `yaml:"key"`
    }

    if err := yaml.Unmarshal([]byte(input), &res); err != nil || value != res.Value {
        quoted := strings.ReplaceAll(value, `'`, `''`)
        return fmt.Sprintf("'%s'", quoted)
    }

    return value
}
于 2021-11-26T12:10:07.597 に答える