NUL 分隔变量

ibu*_*fen 4 bash command-substitution

GNU bash,版本 4.4.19(1)-release (x86_64-pc-linux-gnu)

想法是将变量设置为 NUL 分隔的数据集。这里$samples

然而,这会导致:

警告:命令替换:忽略输入中的空字节

做的时候:

samples="$(find . -type d -iregex './sample[0-9][0-9]' -printf "%f\0" | sort -z)"
Run Code Online (Sandbox Code Playgroud)

以为我可以重复使用这个变量,因为我需要多次迭代相同的值:

while IFS= read -rd '' sample; do
    echo $sample
done<<< "$samples"
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我可以在find命令中使用\nover ,但想知道如果可能的话,一般来说如何使用 NUL 分隔符来做到这一点。\0

(可选)我可以这样做:

while IFS= read -rd '' sample; do
    echo $sample
done< <(find . -type d -iregex './E[0-9][0-9]' -printf "%f\0" | sort -z)
Run Code Online (Sandbox Code Playgroud)

但是 - 因为我需要多次循环它,所以会产生一些非常冗余的代码 - 并且每次都必须运行findsort命令。

也许将结果转换为数组?


  • 这可能吗?
  • 为什么不能按原样使用 NUL 分隔的数据?

Ini*_*ian 8

事实上\0,由于底层的 C 实现,您不能在 bash 字符串上下文中存储空字节。请参阅为什么 $'\0' 或 $'\x0' 是空字符串?应该是空字符,不是吗?.

一种选择是在 sort 命令之后去除空字节,在管道的末尾使用tr并存储结果以解决抛出警告消息的直接问题。但这仍然会使您的逻辑存在缺陷,因为带有换行符的文件名仍然会被破坏。

使用数组,使用mapfileorreadarray命令(在 bash 4.4+ 上)直接从find命令中获取结果

IFS= readarray -t -d '' samples < <(find . -type d -iregex './sample[0-9][0-9]' -printf "%f\0" | sort -z)
Run Code Online (Sandbox Code Playgroud)


fpm*_*phy 6

bash外壳不支持你想要做什么。该zsh壳做的开箱即用。

% mkdir sample11 SAMple12 sample21 sample22 dir1
% ll
total 20
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 dir1
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample11
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 SAMple12
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample21
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample22
% samples=$(find . -type d -iregex './sample[0-9][0-9]' -print0 | sort -z)
% echo $samples
./sample11./SAMple12./sample21./sample22
% echo $samples | od -a
0000000   .   /   s   a   m   p   l   e   1   1 nul   .   /   S   A   M
0000020   p   l   e   1   2 nul   .   /   s   a   m   p   l   e   2   1
0000040 nul   .   /   s   a   m   p   l   e   2   2 nul  nl
0000055
%
Run Code Online (Sandbox Code Playgroud)