Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 从文本文件中随机选择一行,并将该行设置为变量_Batch File - Fatal编程技术网

Batch file 从文本文件中随机选择一行,并将该行设置为变量

Batch file 从文本文件中随机选择一行,并将该行设置为变量,batch-file,Batch File,如何从文本文件中随机选择行/ip,并将其设置为变量 我的意思是: set IP=TheLine/IPFromOfTheFile 试试这个: @echo off setlocal EnableDelayedExpansion set "file=somefile.txt" set "lines=0" for /F "usebackq delims=" %%a in ("%file%") do set /a "lines+=1" set /a "selected=%random%%%%lines%

如何从文本文件中随机选择行/ip,并将其设置为变量

我的意思是:

set IP=TheLine/IPFromOfTheFile
试试这个:

@echo off
setlocal EnableDelayedExpansion
set "file=somefile.txt"
set "lines=0"
for /F "usebackq delims=" %%a in ("%file%") do set /a "lines+=1"
set /a "selected=%random%%%%lines%"
set "lines=0"
for /F "usebackq delims=" %%a in ("%file%") do (
if !lines! equ !selected! set "line=%%a"
set /a "lines+=1"
)
echo %line%
pause

有关批处理文件中阵列管理的更多详细信息,请参阅。

我的解决方案与Aacini的基本相同,但有一些不同的细节:

@echo off

setlocal enabledelayedexpansion
set i=0
for /f "tokens=*" %%x in (%1) do (
    set line[!i!]=%%x
    set /a i += 1
)
set /a j=%random% %% %i%
set ip=!line[%j%]!

文件名是这个批处理的一个参数。

如果我早些时候提到这个问题,我可能会写下与Aacini几乎相同的答案。我给他打+1分

不管怎样,换一种不同的口味怎么样?下面是一个调用PowerShell帮助程序的第一批线性程序

对于/f“delims=“%%I in('powershell“get random(gc\%file%\”)”)设置“IP=%%I”
它比Aacini的解决方案慢,但它确实具有简单的优点*耸肩*如果您的IPs文件包含任何空行,您可以添加一个选择器,仅包含真实性评估结果不为false/empty的行

对于/f“delims=“%%I in('powershell“gc\%file%\”)?{$\u}\ 124; get random“')请设置“IP=%I”

我还考虑过使用
find/c/v“txtfile
获取文本文件中的行数,然后使用
for/f“skip=%randomLineNumber%”
(如aschipfl的答案),但是这比已经提供的其他答案效率要低。

首先,您需要知道文本文件
textfile.txt中的行数:

for /F %%N in ('type "textfile.txt" ^| find /C /V ""') do set NUM=%%N
然后计算从
0
NUM-1
范围内的随机数:

set /A RND=%RANDOM%%%NUM
最后,从文本文件中选择行并将其存储在
行中
RND
保存/F
循环要跳过的行数:

if %RND% EQU 0 (set "SKIP=") else (set "SKIP=skip=%RND% ")
for /F "usebackq %SKIP%delims=" %%L in ("textfile.txt") do (
    set "LINE=%%L"
    goto :NEXT
)
:NEXT

这取决于文本文件不包含任何空行的事实。

基于数组的解决方案似乎应该是最快的,因为它们只读取文件一次。但是,当环境变得非常大时,变量操作变得非常缓慢。因此,基于阵列的解决方案具有非线性性能。如果文件非常大,它们的速度可能会非常慢

对于一个纯粹的基于批处理的解决方案,无论文件大小如何,都能提供良好的线性性能,我喜欢。但是,以
开头的行有问题由于/f下线值的默认值。如果文件为空,它也会失败。这是一个近乎完美的修正版本

@echo off
setlocal
set "file=test.txt"
set "LINE="
for /F %%N in (
  'type "%file%" ^| find /C /V ""'
) do set set /A RND=%RANDOM% %% %%N 2>nul || goto :BREAK
if %RND%>0 (set "skip=skip^=%RND%") else set "skip="
for /F usebackq^ %skip%^ delims^=^ eol^= %%L in ("%file%") do (
  set "LINE=%%L"
  goto :BREAK
)
:BREAK
set LINE
上面还有一个缺陷-如果所选行为空,则由于FOR/F的设计,它将返回下一个非空行

@echo off
setlocal
set "file=\utils\jrepl.bat"
set "ln="
for /f %%N in (
  'type "%file%" ^| find /c /v ""'
) do set /a rnd=%random% %% %%N 2>nul || goto :result
<"%file%" (
  for /l %%N in (1 1 %rnd%) do set /p "ln="
  set "ln="
  set /p "ln="
)
:result
set ln
解决这个问题的“标准”方法是使用FINDSTR为每一行添加行号前缀,然后使用展开查找/替换删除前缀。考虑到行号前缀的存在,我喜欢使用额外的FINDSTR来选择正确的行,而不是依赖FOR/F

@echo off
setlocal
set "file=test.txt"
set "ln="
for /f %%N in (
  'type "%file%" ^| find /c /v ""'
) do set /a rnd=%random% %% %%N + 1 2>nul || goto :result
for /f "delims=" %%L in (
  'findstr /n "^" "%file%" ^| findstr "^%rnd%:"'
) do set "ln=%%L"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
:result
set ln

如果您知道您的所有行都是空的,那么您需要在第一个
for/F
循环中退出管道。但是有两个
for/f
循环+
type | find
比其他答案中建议的单个
for/f
循环效率低。这样做的唯一好处是,如果OP的脚本有多个从其数据文件中提取随机IP的实例,并且数据文件可能在实例之间被修改;我不知道管道是否必要(我在手机上发布了答案…),但我会测试它;无论如何,我发布了这个答案,因为/F
的两个
循环都只迭代一次,这可能具有良好的整体性能(只考虑了一个纯批处理文件解决方案)…@rojo-不一定正确。当环境变得非常大时,变量操作变得非常昂贵,这使得性能非线性。因此,基于“阵列”的解决方案似乎应该是最快的,因为它们只读取文件一次。但实际上,如果文件很大,它们可能会变成狗。这个答案提供了一个解决方案,提供了整体良好的线性性能。
@echo off
setlocal
set "file=\utils\jrepl.bat"
set "ln="
for /f %%N in (
  'type "%file%" ^| find /c /v ""'
) do set /a rnd=%random% %% %%N 2>nul || goto :result
<"%file%" (
  for /l %%N in (1 1 %rnd%) do set /p "ln="
  set "ln="
  set /p "ln="
)
:result
set ln
call jrepl "^.*" $0 /c /jmatch /jbeg "rnd=Math.floor(Math.random()*cnt)+1" /jbegln "skip=(rnd!=ln)" /f test.txt
@echo off
setlocal
set "ln="
for /f "delims=" %%L in (
  'jrepl "^.*" $0 /c /n 1 /jmatch /jbeg "rnd=Math.floor(Math.random()*cnt)+1" /jbegln "skip=(rnd!=ln)" /f test.txt'
) do set "ln=%%L"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
:result
set ln
@echo off
setlocal
call jrepl "^.*" $0 /c /jmatch /jbeg "rnd=Math.floor(Math.random()*cnt)+1" /jbegln "skip=(rnd!=ln)" /f test.txt /o temp.txt
set "ln="
<temp.txt set /p "ln="
del temp.txt
:result
set ln