[英]How to repeat given HEX string
假設我有一個7字節的文件,名為test.dat。 如果我使用HEX編輯器打開test.dat,則代碼為
1F 2E 3D 4C 5B 6A 70
(該代碼沒有重要意義。僅供測試!)
現在,我想通過重復此十六進制代碼1000000次來生成7000000字節的文件,該文件可能稱為000000test.dat。 批處理或bash歡迎使用。
感謝你們對我的幫助!
輕松之路
@echo off
(
For /l %%n in (1,1,1000000) do copy milliontest.dat /B + test.dat /B milliontest.dat /B
) >nul 2>nul
快路
這個工作非常快(在我的舊機器上為0.2秒),這是純的dos批處理解決方案。
@echo off
setlocal EnableDelayedExpansion
>test.dat set /p ".=1234567" <nul
copy test.dat /B tmp.dat >nul
set Times=1000000
(
for /l %%n in (1,1,31) do (
set /A "bit=Times %% 2, Times/=2"
If !bit! equ 1 copy milliontest.dat /B + tmp.dat /B milliontest.dat /B
if !Times! gtr 0 (
copy tmp.dat /B + tmp.dat /B tot.dat /B
del tmp.dat
ren tot.dat tmp.dat
) >nul 2>nul
)
) > milliontest.dat
del tmp.dat
exit /b
正如Aacini所述,我解釋了這種方法。 這種方法是將文件test.dat的字節乘以一百萬。 這使用Bynary乘法 。
“在基數2中,長乘法減少到幾乎微不足道的操作。對於乘法器中的每個'1'位,將被乘數移位一個適當的量,然后將移位后的值相加。根據計算機處理器體系結構和乘數的選擇,可能是當乘法器固定且所需的加法次數很少時,使用硬件位移和加法而不是依賴於乘法指令可以更快地對該算法進行編碼。”
更簡單的方法
這種方式減少了復制命令的數量。 每10個副本重復使用一次結果。 為了獲得結果,此過程使用一百萬個周期的6個周期,因為零的數量為六個。
copy test.dat /B tmp.dat >nul /B
copy tmp.dat /B milliontest.dat /B
For /l %%d in (1,1,6) do (
For /l %%n in (1,1,9) do copy milliontest.dat /B + tmp.dat /B milliontest.dat /B
copy milliontest.dat /B tmp.dat /B
) >nul
對於加倍文件,我嘗試使用:
type tmp.dat>>tmp.dat
但是出現錯誤,而不是我使用COPY。
編輯:用總是復制替換TYPE命令。 TYPE對文本文件起作用。
@echo off
setlocal
set "hex_string=1F 2E 3D 4C 5B 6A 70"
(for /l %%# in (1;1;1000000) do (
(break|set /p=%hex_string% )
))>>hex_file
這會將十六進制字符串打印到文件中1000000次。如果您想以十六進制形式讀取文件,可以檢查certutil
與Guxutils sed
for /L %a in (1,1,999999) do @(sed.exe -ri "s/(.{7})(.*)/\\1\\2\\1/" "test.dat")
sed.exe -ri "s/(.{7})(.*)/\\1\\2\\1/" "test.dat"
將在test.dat中獲得前7個十六進制,其余十六進制並添加第一個7十六進制到最后,然后替換test.dat。
但這會將test.dat重寫到磁盤999999次。
更新,
@echo off
setlocal enabledelayedexpansion
set "s_1="
for /L %%a in (1,1,100) do (set "s_1=!s_1!+")
for /L %%a in (1,1,3) do (
"%sed_path%\sed" -ri "s/.*/%s_1:+=&%/" "test.dat"
)
exit /b
更新的代碼可以快速完成功能,並且僅寫入磁盤3次。
或@echo關閉setlocal enabledelayedexpansion
set "s_1="
for /L %%a in (1,1,1000) do (set "s_1=!s_1!+")
for /L %%a in (1,1,2) do (
"%sed_path%\sed" -ri "s/.*/%s_1:+=&%/" "test.dat"
)
exit /b
這將寫入2次。
但是要根據命令長度的限制。 它不能以
set "s_1="
for /L %%a in (1,1,1000000) do (set "s_1=!s_1!+")
"%sed_path%\sed" -ri "s/.*/%s_1:+=&%/" "test.dat"
exit /b
如果必須保留“ test.dat”,
@echo off
setlocal enabledelayedexpansion
set "s_1="
for /L %%a in (1,1,1000) do (set "s_1=!s_1!+")
for /L %%a in (1,1,2) do (
"%sed_path%\sed" -r "s/.*/%s_1:+=&%/" "test.dat"
)>>test2.dat
exit /b
純批處理解決方案可能會相當慢。
您可以使用我的JREPL.BAT正則表達式文本處理實用程序來實現一個簡單而快速的解決方案。 它是純腳本(混合JScript /批處理),可從XP開始在任何Windows計算機上本地運行。 可以從命令行通過jrepl /?
獲得完整的文檔jrepl /?
或jrepl /??
用於分頁輸出。
jrepl ".*" "Array(1000000+1).join($0)" /m /j /f "test.dat" /o "millionTest.dat"
這個問題還不清楚。 我認為有關HEX的內容無關緊要,要求將“ test.dat”復制到“ milliontest.dat”一百萬次。 在Bash中使用cat
和xargs
一種中等有效的方法是:
for i in {1..1000000} ; do echo test.dat ; done | xargs cat >milliontest.dat
此Bash代碼概括了Einstein1969提供的兩種解決方案:
readonly srcfile=test.dat
readonly multiplier=1000000
readonly destfile=milliontest.dat
readonly base=100
readonly tmp1=$(mktemp)
readonly tmp2=$(mktemp)
declare -i mult=multiplier
curr_src=$srcfile
curr_dest=$tmp1
# 'curr_src_list' is an array containing $base copies of the current source
# file path
declare -a curr_src_list="( {1..$base} )"
curr_src_list=( "${curr_src_list[@]/*/$curr_src}" )
# Initialize the (final) destination file
echo -n > "$destfile"
# Exit immediately if the multiplier is zero or the source file is empty
(( mult == 0 )) && exit 0
[[ -s $srcfile ]] || exit 0
declare -i rem scale
while (( mult > 0 )) ; do
# Loop invariant: (final $destfile) == mult * $curr_src + $destfile
rem=mult%base
div=mult/base
if (( rem != 0 )) ; then
cat -- "${curr_src_list[@]:0:rem}" >> "$destfile"
mult=mult-rem
elif (( mult == base )) ; then
cat -- "${curr_src_list[@]}" >> "$destfile"
mult=0
else
# Determine number ($scale) by which to duplicate $curr_src and divide
# $multiplier.
if (( div < base )) ; then
# Will finish on the next iteration. Copy a smaller amount to
# the temporary file now to minimize wasted copying.
scale=div
mult=base
else
scale=base
mult=div
fi
cat -- "${curr_src_list[@]:0:scale}" > "$curr_dest"
# Current destination becomes new current source
curr_src=$curr_dest
curr_src_list=( "${curr_src_list[@]/*/$curr_src}" )
# Other temporary file becomes new current destination
[[ $curr_dest == "$tmp1" ]] && curr_dest=$tmp2 || curr_dest=$tmp1
fi
done
rm -f -- "$tmp1" "$tmp2"
設置base=2
將給出“快速方式”。 設置base=10
給出了“更簡單的方法”。 如上面的代碼中那樣設置base=100
,意味着只需3次cat
操作即可生成所需的輸出。 在古老的Linux系統上,它的運行時間約為百分之三分之一。 隨着multiplier
設定為一個十億(1000000000)運行cat
5次,完成了超過110秒的相當現代的Linux系統上。 該算法基本上是標准的長乘法算法。 該代碼可能會更簡單一些,但是有時要花費更多的數據到臨時文件中。 此代碼( base=100
)最多應將其復制到臨時文件的1%
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.