Bash

bash mapfile NUL 錯誤?

  • July 8, 2021

在處理 NUL 分隔輸入時, bashmapfile似乎被破壞了。特別是,它沒有-正確處理減號 ( ),將一個後面的空字元串視為行尾標記。

例如:

#!/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 字元時終止一行

bash 版本是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 &lt; &lt;(find . -maxdepth 1 -type f -name '*.txt' -print0)
$ typeset -p files
-bash: typeset: files: not found

來自分詞的 bash 手冊部分

顯式空參數 (""'') 被保留並作為空字元串傳遞給命令。

$$ … $$該詞在分詞和刪除空參數後-d''變為。-d

args在您的工具箱中有一個 shell 腳本來解決參數處理問題會很有幫助。這是一種可能的實現:

#!/bin/sh
printf "%d args:" "$#"
test "$#" -gt 0 && printf " &lt;%s&gt;" "$@"
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: &lt;mapfile&gt; &lt;-d&gt; &lt;-t&gt; &lt;files&gt;

我們看到我們認為我們傳遞給-d選項的 NUL 不存在。選項的參數-d是命令行中的下一個參數:-t!

-d選項的文件mapfile $$ link $$說:

delim的第一個字元用於終止每個輸入行

的第一個字元-t-

因此這兩個呼叫是等價的:

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

這解釋了您所經歷的結果。

引用自:https://unix.stackexchange.com/questions/653059