改行文字を含む環境変数をどのように設定しますか?

改行文字を含む環境変数をどのように設定しますか?

環境変数にRSAキーを改行文字を含むテキストファイルに設定しようとしています。

ファイルから読み込み、それを環境変数に渡そうとするたびに、最初の行の改行文字で停止します。これが起こらないようにするにはどうすればよいですか?

答え1

zsh を除いて、シェル変数は任意のバイトシーケンスを格納できません。他のすべてのシェルの変数にはNULバイトを含めることはできません。の場合、yash有効な文字を形成しないバイトを含めることはできません。

NULバイトを含まないファイルの場合は、POSIXに似たシェルで次のことができます。

var=$(cat file; echo .); var=${var%.}

すべての末尾の改行が削除されることを説明するために、.\n末尾を追加して削除します。.$(...)

上記の方法はzshNULを含むファイルでも機能しますが、特別な連想配列を使用することもzshできます。$mapfile

zmodload zsh/mapfile
var=$mapfile[file]

zsh または bash では、次のものも使用できます。

{ IFS= read -rd '' var || :; } < file

最大最初の NUL バイトを読み取ります。 NUL バイトが見つからない場合は、ゼロ以外の終了状態を返します。ここでコマンドグループを使用すると、少なくともファイルを開くとエラーがわかりますが、シャットダウン状態で読み取りエラーを検出することはできません。

他のコマンドに渡すときにこの変数を引用することを忘れないでください。 Newlineがデフォルトであるため、$IFSzsh以外のPOSIX様シェルでリストコンテキストで引用を解除すると、変数の内容が分割されます($IFS他の文字やワイルドカードに関する他の問題は言うまでもありません)。

だから:

printf %s "$var"

たとえば(いいえ、もちろんそうではありません。これはprintf %s $varSplit + globにecho $var問題が追加されます)。echo


非 POSIX シェルの場合:

ボンシェル:

Bourneシェルはフォーム$(...)${var%pattern}演算子をサポートしていないため、実装するのは難しいです。 1つの方法は、以下を使用してeval引用することです。

eval "var='`printf \\' | cat file - | awk -v RS=\\' -v ORS= -v b='\\\\' '
  NR > 1 {print RS b RS RS}; {print}; END {print RS}'`"

これにより、(t)csh状況はさらに悪化します。見てそこ

を使用すると、空の区切り文字のリストを含むコマンド置換形式をrc使用できます。``(separator){...}

var = ``(){cat file}

答え2

これを達成する1つの方法(ケースを含む0x0)は、バイナリデータをシェル変数にエンコードされた形式で保存することです。

これにはBase64エンコーディングを使用できます(RFC 4648を参照)。

たとえば、

encoded_binary="$( cat binary | base64 -w 0 )"

これは-w 0審美的に非常に満足です(わずかなメモリを節約します)。

バイナリデータを使用するには、再デコードしてパイピングまたはリダイレクトを介してのみ実行できます。

たとえば、

{
        printf '%s\n' "${passphrase}"
        printf '%s' "${encoded_binary}" | base64 -d
} | \
gpg --quiet --batch --passphrase-fd 0 --output - --decrypt

この例では、バイナリは gpg を使用して復号化される OpenPGP メッセージです。

base64/ uuencodeuudecodePOSIXで指定)を代わりに使用できます。

encoded_binary="$( uuencode -m '/dev/stdout' )"
...
printf '%s' "${encoded_binary}" | uudecode -o '/dev/stdout' 

ただし、これは/dev/stdout特殊記号(ファイルではない)でなければなりません。 uudecodeの一部の実装はこの機能を正しくサポートしていますが(例:GNU)、他の実装ではそうではありません(たとえば、BusyBox 'はコミットされており、特定の特別なc7b90dc4d10ccc4f95940f42676ff907cee73272ビルドオプションが設定されている場合にのみサポートしています)。

また、次のような構造がある場合:

encoded_binary="$(read_function | base64 -w 0)"

read_functionPOSIX Shellコマンド言語では直接可能ではありませんが、次のようなものを使用して間接的に実行できる終了状態(またはデコード時に同じ)を確認したい場合があります。これ

答え3

を使用している場合は、zsh次のようにファイルの内容を割り当てることができます。

p="`cat file_to_be_read`"

答え4

パラメータ操作スキームをサポートしていない従来のBourneシェルでは、次のことができます。

NL='
'
var=`cat file`
while case `printf '%s\n' "$var" | wc -l` in "`wc -l < file`" ) break ;; esac
do var=$var$NL; done

最初はファイルというファイルの内容から始めます。これで、末尾の改行がある場合にのみループが開始されますwhile。末尾以外の改行文字にはコマンドの置換が触れないため、問題はありません。

whileループが繰り返されるたびに改行文字が変数にリンクされ、これにはsub(別名)コマンドが含まれていないため、...改行損失は発生しません。

関連情報