Shell
使用 NULL 將標準輸入填充到所需長度的最佳方法
我有以下要求。我有一個輸入流,我需要將其截斷為某個固定長度的字節。我事先不知道輸入流的長度。如果流的長度小於設置的長度,我想用零字節填充它。我嘗試使用
truncate
,但顯然它只能處理不使用標準輸入的文件。例如,假設我們的輸入流 (stdin) 是
TEST
並且我們希望達到 10 字節的長度。那麼輸出流(stdout)應該是TEST\x00\x00\x00\x00\x00
.為了澄清這個例子是用小字元串完成的,但結果應該在大流(兆字節到千兆字節)上表現良好。我使用的容器目前也是基於 Ubuntu 的。
使用 GNU
dd
:$ printf %s test | dd iflag=fullblock bs=10 status=none conv=sync count=1 | hexdump -C 00000000 74 65 73 74 00 00 00 00 00 00 |test......| 0000000a
使用
zsh
, 使用其r
右填充(和截斷)參數擴展標誌(以及p
用於轉義序列的標誌,例如\0
在填充字元串中擴展):$ string=test $ printf %s ${(pr[10][\0])string} | hexdump -C 00000000 74 65 73 74 00 00 00 00 00 00 |test......| 0000000a
雖然請注意,它填充到 10 個字元,而不是 10 個字節。您可以關閉該
multibyte
選項以更改該選項 (set +o multibyte
)。$ string=tést $ printf %s ${(pr[10][\0])string} | hexdump -C 00000000 74 c3 a9 73 74 00 00 00 00 00 00 |t..st......| 0000000b $ printf %s ${(pr[10][\0])string} | wc -mc 10 11
$ set +o multibyte $ printf %s ${(bpr[10][\0])string} | hexdump -C 00000000 74 c3 a9 73 74 00 00 00 00 00 |t..st.....| 0000000a $ printf %s ${(bpr[10][\0])string} | wc -mc 9 10
這些解決方案不能很好地擴展到大於系統上 RAM 量的大小。
對於大尺寸,正如@ilkkachu 在評論中所建議的那樣,
{ printf %s test; cat /dev/zero; } | head -c 1000000000
會更有效(
head -c
不是標準的,但很常見,並且比dd bs=1
一次讀取和寫入一個字節的效率要高得多)。如果輸出到文件,您還可以使用資源限制進行截斷:
( ulimit -f 1048576 # KiB printf %s test cat /dev/zero ) > file