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는 입니다 -.

따라서 다음 두 호출은 동일합니다.

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

이것은 귀하가 겪고 있는 결과를 설명합니다.

관련 정보