BashマッピングファイルNULエラーが発生しましたか?

BashマッピングファイルNULエラーが発生しましたか?

NULで区切られた入力を処理すると、bashがmapfile破損しているようです。特に-、マイナス文字()を正しく処理できず、1の後の空の文字列を行末マークとして扱います。

たとえば、

#!/bin/bash

mkdir /tmp/junk
cd /tmp/junk

touch a.txt b.txt c.txt d-e-f.txt
declare -a files

echo "mapfile using default \\n delimiter"
mapfile -t  files < <(find . -maxdepth 1 -type f -name '*.txt')
typeset -p files

echo
echo "mapfile using NUL delimiter"
mapfile -d'' -t  files < <(find . -maxdepth 1 -type f -name '*.txt' -print0)
typeset -p files

echo
echo "and again"
mapfile -d$'\0' -t  files < <(find . -maxdepth 1 -type f -name '*.txt' -print0)
typeset -p files
$ ./test.sh 
mapfile using default \n delimiter
declare -a files=([0]="./d-e-f.txt" [1]="./a.txt" [2]="./c.txt" [3]="./b.txt")

mapfile using NUL delimiter
declare -a files=([0]="./d-" [1]="e-" [2]="f.txt")

and again
declare -a files=([0]="./d-" [1]="e-" [2]="f.txt")

これはバグですか?それとも重要なことを忘れて間違っているのでしょうか?

マッピングファイルのエントリは次のman bashとおりです。

-ddelim の最初の文字は、改行文字ではなく各入力行を終了するために使用されます。 delimが空の文字列の場合、mapfileはNUL文字を読み取ると行を終了します。

バッシュバージョンは5.1.8(1)-release次のとおりです

$ bash --version
GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

修正する

これ以上のことは、配列の既存の要素がすでに存在する場合(上記のように)破壊するように見えますが、存在しない場合は作成しないことです。

$ unset files
$ mapfile -t -d'' files < <(find . -maxdepth 1 -type f -name '*.txt' -print0)
$ typeset -p files
-bash: typeset: files: not found

ベストアンサー1

~から単語分割の bash マニュアルセクション:

明示的な空の引数(""または'')は保持され、空の文字列としてコマンドに渡されます。 [...]単語はトークン化と空の引数を削除した後に-d''行われます。-d

argsパラメータ処理の問題を解決するには、ツールボックスにシェルスクリプトがあると便利です。可能な実装は次のとおりです。

#!/bin/sh
printf "%d args:" "$#"
test "$#" -gt 0 && printf " <%s>" "$@"
echo

# Source:
# https://lists.gnu.org/archive/html/help-bash/2021-07/msg00044.html

試してみてくださいmapfile -d'' -t files

$ args mapfile -d'' -t files
4 args: <mapfile> <-d> <-t> <files>

オプションに渡されたと思った NUL が-d存在しないことを確認します。このオプションの引数は、コマンドラインの次-dの引数です。-t

-dオプションに関するドキュメントmapfile [協会]説明する:

最初の文字Delim各入力ラインを終了するために使用されます。

の最初の文字-tはです-

したがって、次の2つの呼び出しは同じです。

mapfile -d'' -t files
mapfile -d '-' files

これはあなたが経験している結果を説明します。

おすすめ記事