如何重复给定HEX字符串

时间:2016-02-25 07:30:58

标签: bash batch-file hex repeat

假设我有一个7字节的文件,名为test.dat。 如果我用HEX编辑器打开test.dat,代码将是

1F 2E 3D 4C 5B 6A 70

(代码没有重大意义。只是为了测试!)

现在,我想要生成7000000字节文件,它可以被称为milliontest.dat,通过重复这个十六进制代码1000000次。欢迎批量或bash。

感谢您帮助我!

6 个答案:

答案 0 :(得分:5)

Easy-Way

@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 Multiplication

  

&#34;在基数2中,长乘法减少到几乎无足轻重的操作。   对于每个&#39; 1&#39;乘法器中的位,移位被乘数   适当的数量,然后将移位的值相加。取决于   计算机处理器架构和乘数的选择,它可能是   使用硬件位移和加法编码此算法的速度更快   而不是依赖于乘法指令,当乘数   是固定的,所需的添加数量很少。&#34;

更简单的方法

这样可以减少复制命令的数量。每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。

编辑: 用COPY Always替换TYPE命令。 TYPE适用于文本文件。

答案 1 :(得分:0)

@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

答案 2 :(得分:0)

使用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个HEX,其余的HEX并将前7个HEX添加到最后。然后替换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

答案 3 :(得分:0)

纯批量解决方案可能相当慢。

您可以使用我的JREPL.BAT regex text processing utility来实现简单快速的解决方案。它是纯脚本(混合JScript /批处理),可以在XP之后的任何Windows机器上本机运行。可以从命令行通过jrepl /?jrepl /??获取完整文档以获取分页输出。

jrepl ".*" "Array(1000000+1).join($0)" /m /j /f "test.dat" /o "millionTest.dat"

答案 4 :(得分:0)

这个问题有点不清楚。我认为关于HEX的东西是无关紧要的,并且要求是复制&#39; test.dat&#39;进入&#39; milliontest.dat&#39;一百万次。使用catxargs在Bash中执行相对有效的方法是:

for i in {1..1000000} ; do echo test.dat ; done | xargs cat >milliontest.dat

答案 5 :(得分:0)

这个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给出&#34;快速方式&#34;。设置base=10会提供更简单的方式&#34;。设置base=100,如上面的代码所示,意味着只需3 cat个操作即可生成所需的输出。它在古老的Linux系统上以大约百分之三秒的速度运行。当multiplier设置为十亿(1000000000)时,它运行cat 5次,并在一个相当现代的Linux系统上以超过11秒的时间完成。 该算法基本上是标准的长乘法算法。代码可能稍微简单一些,但有时会将更多数据复制到临时文件。此代码(带base=100)最多应复制1%到临时文件