
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
とおりです。
-d
delim の最初の文字は、改行文字ではなく各入力行を終了するために使用されます。 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
明示的な空の引数(
""
または''
)は保持され、空の文字列としてコマンドに渡されます。 [...]単語はトークン化と空の引数を削除した後に-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
これはあなたが経験している結果を説明します。