批处理文件从文件中提取随机字符串并循环随机次数

时间:2012-11-29 23:11:00

标签: windows random for-loop batch-file

我正在尝试创建一个批处理文件,该文件将在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% 

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

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

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

1 个答案:

答案 0 :(得分:1)

你有一些问题:

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

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

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

  • var2的计算效果不佳。如果%RANDOM%*9超过4字节signed int的最大值,则可能会失败。我也不认为它给你想要的值分配。您应该像使用随机行号一样使用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
)