やりたいshuf --zero-terminated
ヒアドキュメントを含む複数行の文字列。
Bashとdashのヒアドキュメントはこれをサポートしていません。変数にnullを格納することはできません。nullはコマンド置換から削除され、文字どおりに書き込むことはできません。また、ヒアドキュメント内でANSI-Cクォートを使用することはできません。どちらのシェルもnullに対応しておらず、一般的に(Cスタイルの)文字列ターミネーターとして扱われます。
いくつかのオプションがあります: 実際のファイルを使用 、zshを使用、プロセス置換を使用、または標準入力を使用します。
あなたはできますは、zshで必要なことを正確に実行できます。
zsh% null=$(printf '\x00')
zsh% hexdump -C <<EOT
heredoc> a${null}b${null}
heredoc> EOT
00000000 61 00 62 00 0a |a.b..|
00000005
ただし、ヒアドキュメントには暗黙の終了改行があり、これは望ましくない場合があります(最後のnullの後のshuf
の追加フィールドになります)。
Bashの場合は、ヒアドキュメントとほぼ同等の プロセス置換 をprintf
またはecho -e
と組み合わせて使用して、インラインでnullを作成できます。
bash$ hexdump -C < <(
printf 'item 1\x00item\n2\x00'
)
00000000 69 74 65 6d 20 31 00 69 74 65 6d 0a 32 00 |item 1.item.2.|
0000000e
これは、ヒアドキュメントと完全に同等であるとは限りません。これらは、シェルによって実際にファイルに密かに入れられることが多いためです(特にシーク可能性が重要です)。
おそらく改行の終了を抑制したいので、そこでコマンド内でヒアドキュメントを内部的に使用することさえできません-出力をきめ細かく制御するために安全であればprintf
/echo -ne
でなければなりません。
ダッシュでプロセス置換を行うことはできませんが、どのシェルでも、サブシェルから標準入力をパイプすることができます。
dash$ (
printf 'item 1\x00'
printf 'item\n2\x00'
) | hexdump -C
00000000 69 74 65 6d 20 31 00 69 74 65 6d 0a 32 00 |item 1.item.2.|
0000000e
shuf
はデフォルトで標準入力から読み取ってくれるので、私が理解しているように、具体的なユースケースで機能するはずです。より複雑なコマンドがある場合は、パイプラインの右側にいると、スコープ付けによって混乱する要素が発生する可能性があります。
最後に、printf
を使用して実際のファイルにデータを書き込み、ヒアドキュメントの代わりにそれを使用できます。そのオプションは 他の答え でカバーされています。後でファイルを確実にクリーンアップする必要があります。ライブのセキュリティ上の懸念がある場合は、安全なファイル名を作成するために mktemp
などを使用することもできます。
皆さん、ありがとうございました。私はあなた全員に基づいて1つの回答ベースを投稿させてください。
このスクリプトは、bashとdashでうまく機能します。実際のファイルや bashでのプロセス置換 は必要ありません。エンティティのエスケープ問題を心配する必要がない場合でも、余分な低速の外部プログラム呼び出しは必要ありません。 %s
in C printf 、ただし、シェル自体の文字列エスケープには注意が必要です。
#!/bin/sh
printf '%s\0' "[tag1]
key1=value1
key2=value2
[/tag1]
" "[tag2]
key3=value3
key4=value4
[/tag2]
" | shuf --zero-terminated
#also see man printf(1)
shuf
のみ(一般的なヒアドキュメントの代替を意図していない):
shuf --echo "[tag1]
key1=value1
key2=value2
[/tag1]" "[tag2]
key3=value3
key4=value4
[/tag2]"
ヒアドキュメントでやりたいことができるとは思いません。ただし、次の例に示すように、echo
を使用するのは簡単です。
$ cat demo
#!/bin/bash
echo -ne "one\0" > outfile
echo -ne "two\0" >> outfile
echo -ne "three\0" >> outfile
$ ./demo
$ od -a outfile
0000000 o n e nul t w o nul t h r e e nul
0000016
$