shell 中处理 NULL 字符

shell 中处理 NULL 字符

shell 中有处理 NULL 字符的可移植方法吗?

一个典型的示例是将 with shell(并且仅 shell)的输出拆分find ... -print0为管道或命令替换结果。我所说的便携式理想情况下是指炮弹不像例如那样强大bashzsh不会被卡住的东西。这在“裸 POSIX shell”(任何 POSIX 版本)中可能吗?

答案1

POSIX 没有设想处理文本嵌入null字符的标准实用程序。-print0您使用的选项本身find就是一个GNU不受POSIX.

null使用 shell 脚本处理包含 s 的数据流的一种方法POSIX是首先将其转换为真实文本od并处理该文本。

无论如何,如果您有GNU find,那么您可能还有其他GNU实用程序,这些实用程序一开始就没有该限制。

答案2

Bash 可以使用read's-d选项来处理它,例如

find . -print0 | while read -r -d '' line; do
    # something with $line
done

但不知道这是否是 POSIX。

答案3

找到类似的问题,这是我在一段时间后想出的...不确定这在 POSIX shell 中是否可行。在 Cygwin 中尝试过这个。只是为了好玩,用空字符弥补了一个问题。

想象的问题如下:您有(一些)文件中包含空字符。您不确切知道这些文件是什么或它们位于何处。您的任务是删除所有此类可能文件的空字符。

下面,第一个命令将显示包含空字符的行,然后另一个命令将空字符转换为换行符(最后一个命令删除临时文件):

find . ! -type d -exec perl -ne '/\000/ and print;' {} \; > /tmp/null-lines
tr -s '\000' '\n' < /tmp/null-lines > with-null-lines.txt
rm /tmp/null-lines

之后,需要读取结果行的每一行并查找该行属于哪个文件。为此,我首先保存需要检查的所有文件,然后查看其中是否有匹配的行:

find . ! -type d -print > files.txt
while read line; do while read line2; do if grep -q "$line2" "$line"; then echo "$line" >> examination.txt; fi; done < with-null-lines.txt; done < files.txt

(重新运行循环之前,删除文件“examination.txt”)

现在,我们计算出现的次数,如果出现的次数超过 1,则很可能有多个空字符(当然,如果只有一个,查找起来就会变得更加困难)。

uniq -c examination.txt | grep -v "1"

它应该在那里列出(大多数)包含空字符的文件。忽略“with-null-lines.txt”这一行。此外,如果文件中存在相同的文本,那么您可能还会在其中看到一些无辜的文件,需要从列表中手动清除。

  1. 如果空字符不在换行符的位置,只需删除它们:

    uniq -d examination.txt > files-to-clean.txt
    while read line; do ex -s +"%s/\%x00//g" -cwq $line; done < files-to-clean.txt
    

    或者使用tr, 对于文件:

    tr -d '\000' < inputfile > outputfile
    
  2. 要清除文件中的空字符(假设它们都位于换行符的位置),请使用以下命令:

    tr -s '\000' '\n' < inputfile > outputfile
    

    tr没有过多地研究如何一次处理多个文件。

相关内容