我的python代码如下所示:
def test():
pipe = sp.Popen( ["test.sh"], stdin=sp.PIPE)
data = "".join([chr((s)%17) for s in range(0,33)])
os.write(pipe.stdin.fileno(), data)
pipe.stdin.write("endoffile")
if __name__ == "__main__":
test()
它调用以下简单的bash shell脚本,它只是将stdin写入文件(脚本称为test.sh)
#!/bin/bash
VALUE=$(cat)
echo "$VALUE" >> /tmp/test.txt
当我运行python代码时,我希望test.txt包含值0x01..0x10两次,之后字符串" endoffile"
然而,这里是文件的hexdump:
0000000: 0102 0304 0506 0708 090a 0b0c 0d0e 0f10 ................
0000010: 0102 0304 0506 0708 090a 0b0c 0d0e 0f65 ...............e
0000020: 6e64 6f66 6669 6c65 0a ndoffile.
似乎缺少一个字节(0x10)。
我在这里缺少什么?
---更新
将test()函数更改为:
def test():
pipe = sp.Popen( ["test.sh"], stdin=sp.PIPE)
data = "".join([chr((s)%16+1) for s in range(0,32)])
os.write(pipe.stdin.fileno(), data)
pipe.stdin.write("endoffile")
似乎要解决这个问题。 这似乎与将chr(0)发送到管道有关。
答案 0 :(得分:1)
range()
是右侧专有。
range(0, 33)
是[0, ..., 32]
,可能是因为这样你可以range(0, len(sequence))
没有一个错误。
从32 % 17 == 15 == 0x0f
开始,您期望的字节'\x10'
从未成为列表中的一部分。
编辑1:
输出中也缺少零个字符'\x00'
。如果您使用VALUE=$(cat)
,cat
的输出将由shell处理。
SingleUnix / POSIX似乎对此事保持沉默。但很明显,由于Unix环境要求两者都是C-style zero terminated strings,因此不能将'\0'
作为shell变量值(或该名称的名称)的一部分。实际上,我希望VALUE
的值为空字符串。
编辑2
经过一番挖掘,我可以说至少ash
implementation忽略'\0'
处理反引号提供的输入。读取输入,直到明确跳过EOF和空字符。
bash
做同样的事情,甚至有与事件相关的明确(即使已注释掉)warning。