使用Perl解析由null字节分隔的字符串

10
/proc文件系统包含运行进程的详细信息。例如,在Linux上,如果您的PID是123,那么该进程的命令行将在/proc/123/cmdline中找到。 cmdline使用空字节来分隔参数。
我怀疑应该使用unpack,但我不知道如何使用。我的若干尝试使用各种模板(“x”,“z”,“C*”,“H*”,“A*”等)都没有起作用。

我的最终结果(能够读取原始命令行字符串)是通过执行 $line =~ s/\0/ /g; 实现的(感谢 lanzz 的启发)。 - emx
my @cmd = $line =~ /([^\0]+)/g 可能更加简洁。如果需要,你可以使用 "@cmd" 来重新组装 cmd。 - TLP
4个回答

9
一个简单的split("\0", $line)就能很好地完成任务。

5

您可以将$/设置为"\0"。例如:

perl -ne 'INIT{ $/ = "\0"} chomp; print "$_\n";' < /proc/$$/environ

3
这可以通过命令行开关-l-0或手动更改$/来完成。 -l-0的顺序很重要,可以多次使用。
感谢您激励我阅读perlrun文档。
示例:
# -0    : set input separator to null
# -l012 : chomp input separator (null) 
#         and set output separator explicitly to newline, octol 012.
# -p    : print each line
# -e0   : null program

perl -0 -l012 -pe0 < /proc/$$/environ

.

# -l    : chomp input separator (/n) (with -p / -n)
#         and set output separator to current input separator (/n)
# -0    : set input separator to null
# -p    : print each line
# -e0   : null program

perl -l -0 -pe0 < /proc/$$/environ

.

# partially manual version
# -l    : chomp input separator (/n) (with -p / -n)
#         and set output separator to current input separator (/n)
# -p    : print each line
# -e    : set input record separator ($/) explicitly to null
perl -lpe 'INIT{$/="\0"}'  < /proc/$$/environ

打包问题:

# DOESN'T WORK:
# -l0   : chomp input separator (/n) (with -p / -n)
#         and set output separator to \0
# -e0   : null program
perl -l0 -pe0

.

# DOESN'T WORK:
# -0    : set input separator to null (\0)
# -l    : chomp input separator (\0) (with -p / -n)
#         and set output separator to current input separator (\0)
# -e0   : null program
perl -0l -pe1

3

我并不建议使用这个方法,但是为了提供资讯:可行的解包模板是unpack "(Z*)*", $cmdlineZ用于打包和解包以空字符结尾的字符串,但因为它是一个字符串类型,所以在它后面加上数字或星号表示的是长度,而不是重复次数——Z*解包任意长度的一个以空字符结尾的字符串。要解包任意数量的这种字符串需要将其括在括号中,然后对括号分组应用重复操作,这样就可以得到(Z*)*


感谢您的澄清,很高兴学到了有关pack/unpack的知识。 - emx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接