批处理代码将每个字符增加1

时间:2016-12-04 06:45:34

标签: batch-file for-loop increment

我们假设您有一个文本文件,其中包含以下详细信息:

User1
ABCDEF

所以我想做的是将每个字符增加1,即输出应如下:

Vtfs2
BCDEFG

我想将这两个输出存储到两个不同的变量中,即:

Set var1=Vtfs2
Set var2=BCDEFG

我知道有一种使用for /f的方法,但我还没到达那里。 以下是我能想出的所有内容:

for /f "tokens=* delims=" %%x in (Myfile.txt) do (
    set var=%%x+1
)

但它的作用是以数字的形式加起来。那么我该如何将它应用于角色。

1 个答案:

答案 0 :(得分:0)

for /F用于读取和解析文本并将其拆分为标记,但它无法将字符转换为代码(ASCII)并返回。

我想到在字符串中获取字符代码的唯一方法是使用CertUtil实用程序,该实用程序提供动词-encodehex以将文本文件转换为十六进制编码的文件和动词-decodehex进行相反的转换。由于这依赖于十六进制表示中的字符代码,并且手头的任务需要一些数学,我们需要进行十六进制到十进制的转换,反之亦然;前者可以通过set /A实现,并且能够在以0x为前缀时解释十六进制数字;后者可以使用名为=ExitCode的未记录的内置变量来完成,该变量包含最新exit code的十六进制表示形式,而后者又可以由cmd /C设置exit %NUMBER%,其中%NUMBER%是十进制退出代码(退出代码和ErrorLevel并不总是相同,但在我们的情况下它们是)。

所以,让我们把所有这些东西放在一起吧:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set /A "_MIN=0x20" & rem // (minimal character code to regard for rotation)
set /A "_MAX=0x7F" & rem // (maximal character code to regard for rotation)
set "_TMP=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (path to temporary file)

rem // Convert provided rotation offset parameter to number:
set "OFFSET=%~3"
set /A "OFFSET+=0"
rem // Convert input text file to temporary hexadecimal-encoded file:
> nul CertUtil -encodehex "%~1" "%_TMP%" || (
    >&2 echo The system cannot find the file specified.
    exit /B 1
)
rem // Read temporary hexadecimal-encoded file, then clear it:
for /F "tokens=1,* delims=  " %%K in ('type "%_TMP%" ^& ^> "%_TMP%" rem/') do (
    rem // Get line with the preceding position number removed:
    set "NEW= " & set "LINE=%%L"
    setlocal EnableDelayedExpansion
    rem // Iterate through all character codes of the current line:
    for %%K in (!LINE:~^,48!) do (
        rem // Retrieve a single character code as decimal number:
        set /A "CODE=0x%%K"
        rem // Check whether character code is in applicable range:
        if !CODE! GEQ %_MIN% if !CODE! LEQ %_MAX% (
            rem /* Perform rotation by adding the given offset;
            rem    adapt result if predefined range is left: */
            set /A "CODE+=OFFSET%%(1+_MAX)"
            if !CODE! LSS %_MIN% set /A "CODE+=1+_MAX-_MIN"
            if !CODE! GTR %_MAX% set /A "CODE-=1+_MAX-_MIN"
        )
        rem /* Convert rotated character code to hexadecimal number,
        rem    collect the character codes in a single line: */
        cmd /C exit !CODE!
        set "NEW=!NEW!!=ExitCode:~-2! "
    )
    rem // Write line of collected character codes to temporary file:
    >> "%_TMP%" echo(!NEW:~1,-1!
    endlocal
)
rem // Convert temporary hexadecimal-encoded file to output text file:
> nul CertUtil -f -decodehex "%_TMP%" "%~2" || (
    >&2 echo The system cannot find the path specified.
    exit /B 1
)
rem // Clean up temporary file:
del "%_TMP%"

endlocal
exit /B

这个脚本 - 我们称之为rotate-chars.bat - 需要三个命令行参数:输入文本文件的路径,输出文本文件的路径(可能与输入文件的路径相同)直接修改它)和旋转字符代码的数量(根据你的问题,这应该设置为+1)。因此,当使用以下命令行调用脚本时......:

rotate-chars.bat "test.txt" "test_NEW.txt" +1

...并且具有以下test.txt ...:

的内容
User1
ABCDEF

...,临时文件在脚本中首次执行CertUtil后立即保存以下内容:

0000  55 73 65 72 31 0d 0a 41  42 43 44 45 46 0d 0a      User1..ABCDEF..

执行for /F循环后,临时文件包含:

56 74 66 73 32 0D 0A 42 43 44 45 46 47 0D 0A

您可以看到每个字符代码都增加了一个,除了脚本顶部给出的范围之外(0x200x7F;外部任何代码都没有触及)。省略了初始位置(0000)和最终文本列,因为它们不需要进行反向转换。

在第二次执行CertUtil之后,返回的输出文件test_NEW.txt将包含以下数据:

Vtfs2
BCDEFG

请注意,如果字符代码在一个边界处移出指定范围,例如0x7E + 5 = 0x83,其边界为0x20和{{ 1}},它移到了另一端,如0x7F(= 0x23 - (0x83 + 1)+ 0x7F);这就是使用术语“轮换”的原因。

要将生成的文本文件的前两行存储到变量中,您可以执行以下操作:

0x20