【问题标题】:batch file IF vs ECHO giving different results批处理文件 IF 与 ECHO 给出不同的结果
【发布时间】:2014-03-16 16:13:35
【问题描述】:

我遇到了这个奇怪的问题 我正在使用 wget 下载文件,然后将 var 设置为文件的第一行,然后与字符串进行比较以验证文件。奇怪的是 var 按预期设置, echo 工作 fien 但是当我使用 if 进行比较时, var 爆炸了。看下面的例子:

set /p first_line=< c:\data.dsv
echo %first_line%
if %first_line% == SomefirstLine GOTO Success

批处理运行时,echo 给出正确的 var 值,但如果它给出前 3 行,为什么会发生这种奇怪的事情?

【问题讨论】:

    标签: windows batch-file


    【解决方案1】:

    原因可能是下载文件中的行终止。如果行以 0x0A(换行符)结尾而没有 0x0D(回车),则set /p 将读取直到第一个 0x0D、文件结尾或最大长度被检索到。

    echo命令会一直输出到第一个0x0A,但是变量内容是这三个“行”,可以使用set first_line验证查看变量的真实内容。

    你可以使用

    set "first_line="
    for /f "delims=" %%a in (c:\data.dsv) do set "first_line=%%a" & goto done
    :done
    

    或者,如果您更喜欢使用 set /p 方法读取文件,则对检索到的变量执行相同的处理以提取所需的值

    set /p first_line=< c:\data.dsv
    set "first_first_line="
    for /f "delims=" %%a in ("%first_line%"
    ) do if not defined first_first_line set "first_fisrt_line=%%a"
    

    已编辑 - 操作系统版本似乎会影响其工作方式。

    第二个提议的代码在一台装有 XP 的机器上进行了测试,它可以工作,但在 Windows 7 中它不能工作。测试后,for 命令不会在 0x0A 字符上拆分字符串,而是删除 0x0A 并将三行合并为分配给变量的一行。因此,只有第一个选项(只有 for 循环)适用于两个版本。

    选项 3 - 为避免将整个文件读入内存,可以解析 set 命令的输出以检索真正的第一行。

    @echo off
    
    :: get data
        set /p "first_line="<c:\data.dsv
    
    :: show data
        echo(data retrieved with set /p
        echo(----------------------------------------------------
        echo(%first_line%
        echo(----------------------------------------------------
        set first_line
        echo(----------------------------------------------------
        echo(
    
    :: get data 2
        for /f "tokens=1,* delims==" %%a in ('set first_line^|find "first_line="') do set "first_line=%%b"
    
    :: show data
        echo(data retrieved with for
        echo(----------------------------------------------------
        echo(%first_line%
        echo(----------------------------------------------------
        set first_line
        echo(----------------------------------------------------
    
    :: test data    
        set "SomeFirstLine=...."
        if "%first_line%"=="SomeFirstLine" GOTO Success
    

    【讨论】:

    • 感谢您的快速回复,但是这是否会遍历整个平面文件,我那里有 150 万条记录,这将浪费大量资源和时间。我是新手,正在学习,如果我错了,请告诉我
    • @fdk2dublin,在第一个代码块中,所有文件都被读入内存,但只处理了第一行。第二个代码块使用与您相同的set /p,然后使用for 命令拆分检索到的数据。在您的情况下,第二种方法可能更好。
    • 感谢 MC ND,我正在尝试使用第二个代码 sn-p(for /f),但长度仍然试图干扰并且不会执行并设置 first_first_line,感谢任何帮助提前。或者如果有任何其他快速的方法来解决这个问题
    • @fdk2dublin,请查看更新后的答案。似乎解析器会随着操作系统版本的变化而改变其行为。
    • @fdk2dublin,我提供了第三个选项以避免将完整文件读入内存。无论如何,从最近使用 for 命令的测试中,我在 0.11 秒内将一个 280MB 的文件加载到内存中,而第一种方法在处理第一行后将其丢弃。我不知道你的数据量是多少,但如果它不是很大,也许单个 for 命令可以解决问题。
    【解决方案2】:

    注意 if 比较中的 double quotes - 它们保护它免受 spaces&amp; 字符的影响。

    set /p first_line=< c:\data.dsv
    echo %first_line%
    if "%first_line%" == "SomefirstLine" GOTO Success
    

    【讨论】:

    • @foxDrive,我以前试过这个,但案例是 MC ND 提到的。我可以使用 MC ND 提到的第一种方法使这个东西工作,不知道为什么第二种方法(由 MC ND)不起作用。
    • 字符串中是否有空格、&amp; % 或其他有毒字符?这不是问题所在。
    猜你喜欢
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    相关资源
    最近更新 更多