0

我正在尝试创建一个批处理文件,该文件将在 2 到 10 之间随机循环次数,并每次从文本文件中提取一条随机行并显示它。

set var1=%RANDOM%
set /a var2=(var1*9/32768)+2
for /l %%x in (1,1,%var2%) do (
set "lines=0" 
for /f "tokens=*" %%a in (c:\myfile.txt) do set /a "lines+=1" 
set /a "skip=%var1% %% lines" 
if %skip% lss 1 (set "skip=") else (set "skip=skip=%skip%")
for /f "skip=%skip% tokens=*" %%a in (c:\myfile.txt) do set "item=%%a"&goto display

:display
echo %item%
)

这是两段不同的代码,它们各自独立工作,但我无法将它们放在一起。

每次运行时,下面的代码都会显示文件中的随机行。

set "lines=0" 
for /f "tokens=*" %%a in (c:\myfile.txt) do set /a "lines+=1" 
set /a "skip=%random% %% lines" 
if %skip% lss 1 (set "skip=") else (set "skip=skip=%skip%") 
for /f "%skip% tokens=*" %%a in (c:\myfile.txt) do set "item=%%a"&goto display 
:display 
echo %item% 

此代码将显示 2 到 10 次之间的 1。

@echo off
set var1=%RANDOM%
set /a var2=(var1*9/32768)+2
for /l %%x in (1,1,%var2%) do (
echo 1
)

我可能只是忽略了显而易见的事情,但我没有做很多批处理脚本。

4

1 回答 1

1

你有几个问题:

  • 您在带括号的块(DO 子句)中定义变量skip,然后尝试%skip%在同一个循环中使用。这是行不通的,因为在解析整个代码块时会扩展变量 - 在设置值之前!通常解决方案是使用延迟扩展,但您不能在 FOR /F 选项中使用延迟扩展。解决方案是在块外调用。

  • 您的逻辑对每次迭代使用相同的随机数。我将您声明的要求解释为您希望为每次迭代使用不同的随机数。

  • 你的 GOTO 打破了你的 FOR 循环。如果您发出 GOTO,循环将不会进行下一次迭代。

  • 你的计算var2不好。如果%RANDOM%*9超过 4 字节有符号整数的最大值,它可能会失败。我也不认为它给出了你想要的价值分布。您应该像使用随机行号一样使用 mod 运算符。

  • SKIP 选项的值必须 >= 1。如果您想要 0,则必须完全忽略该选项。您的隔离代码可以正确执行此操作,但是您损坏的代码是,嗯,损坏了:-)

其他改进:

  • 每次迭代计算文件中的行数。你只需要这样做一次。

  • 使用 FIND 计算行数并使用 FOR /F 捕获值效率更高。FOR /F 忽略空行,因此我使用 FINDSTR 查找所有非空行,并将这些结果通过管道传递给 FIND 以获取计数。

  • 使用TOKENS=*将去除前导空格,而DELIMS=将保留整行。

  • 默认的 EOL 选项是EOL=;,这意味着任何以开头的行都;将被忽略。将 EOL 设置为空需要在每个空格之前使用插入符号且相等且不带引号的奇怪语法。

  • 我在文件名周围添加了引号并添加了 USEBACKQ 选项,以防您的文件名包含空格。

这是一个有效的解决方案

@echo off
setlocal
set "file=c:\myfile.txt"
for /f %%N in ('findstr "." "%file%"^|find /c /v ""') do set lines=%%N
set /a "iterations=%random% %% 8 + 2"
for /l %%N in (1 1 %iterations%) do call :printRandomLine
exit /b

:printRandomLine
set /a "skip=%random% %% %lines%"
if %skip% lss 1 (set "skip=") else set "skip=skip^=%skip%"
for /f usebackq^ %skip%^ delims^=^ eol^= %%A in ("%file%") do (
  echo %%A
  exit /b
)
于 2012-11-30T06:13:11.470 回答