bash: 文字列区切り文字まで標準入力から読み込む

bash: 文字列区切り文字まで標準入力から読み込む

任意のバイトを含む 2 つのファイルがあるとします:./delimiterおよび./data

./data内のバイトシーケンスの最初の出現までを読み取ります./delimiter

Bash を使用してこれを実行するにはどうすればよいですか?

例:

  • の内容./delimiter
    world
    
  • の内容./data
    helloworld
    
  • 期待される結果:
    hello
    

類似/同等の質問:

注:文字列でread -d delimはなく、単一文字の区切り文字のみをサポートしているため、問題は解決されません。また、結果は変数に格納されますが、変数はNULバイトをサポートしていません。出力を にしたいのですstdout

答え1

Perl が救世主です!

perl -e 'local $/;
         open $de, "<", "delimiter" or die $!;
         $/ = <$de>;
         open $da, "<", "data" or die $!;
         chomp( $first = <$da> );
         print $first;'

特殊変数$/入力レコードセパレータを設定します。地元これを使用すれば、ファイル全体を読み込むことができます(「スラーピング」とも呼ばれます)。次に、ダイヤモンド演算子を使用してファイルから読み込みdelimiter、セパレータをその内容に設定します。次に、ファイルから最初のレコードを読み込みdataかむそこからレコード区切り文字を削除します。

答え2

zsh(任意のバイトシーケンスを変数に格納できる唯一のシェル)では、dataと がdelimiter通常のファイル (または少なくとも mmap() 可能なファイル) であると仮定すると、次の操作を実行できます。

zmodload zsh/mapfile

set +o multibyte # necessary so sequences of bytes that
                 # happen to form valid characters may be
                 # broken in the middle if necessary.

firstpart=${mapfile[data]%%$mapfile[delimiter]*}

または:

zmodload zsh/mapfile
set +o multibyte # necessary so sequences of bytes that
                 # happen to form valid characters may be
                 # broken in the middle if necessary.

delimiter=$mapfile[delimiter]
parts=( ${(ps[$delimiter])mapfile[data]} )

firstpart=$parts[1]

(非常に効率的であることや、数百メガバイトを超えるファイルに対して適切に拡張できることは期待しないでください)。

その部分をそのまま印刷するには、次のようにします。

print -rn -- $firstpart

または

printf %s $firstpart

関連情報