我需要一种方法来使用批处理来查看文本文件的每一行,并删除该文本文件中的一半行,选择要随机删除的行。
这是为了模拟D& D游戏中的锦标赛。我所需要的只是一种方法来扼杀每轮比赛的获胜者。我可以轻松制作一个复制文本文件的批处理文件,并为每一轮重命名,但是减少了一半,我不擅长。
编辑:我想要一个批处理文件来执行此操作,因为它需要花费很多时间在桌面上手动完成。此外,该游戏非常古老且角色扮演重点突出,因此游戏中有一个NPC角色的实际列表,PC将想知道他们的朋友在比赛中的表现。
答案 0 :(得分:1)
此方法保留原始行的顺序。
@echo off
setlocal EnableDelayedExpansion
rem Generate an array of line numbers with all file lines
for /F "delims=:" %%a in ('findstr /N "^" input.txt') do (
set "n[%%a]=%%a"
set "lines=%%a"
)
rem Delete half the numbers in the array in random order
set /A halfLines=lines/2
for /L %%n in (%lines%,-1,%halfLines%) do (
set /A rnd=!random!*%%n/32768+1
set /A n[!rnd!]=n[%%n]
set "n[%%n]="
)
rem Reorder the resulting elements
for /F "tokens=2,3 delims=[]=" %%i in ('set n[') do (
set "l[%%j]=1"
set "n[%%i]="
)
rem Copy such lines
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" input.txt') do (
if defined l[%%a] (
echo(%%b
set "l[%%a]="
)
)) > output.txt
答案 1 :(得分:1)
问题中指定的设计存在缺陷。你不能随意删除一半的线,因为对于任何给定的游戏,你可能最终得到2个赢家,或者没有赢家。输入文件必须具有指定哪些参赛者互相比赛的结构,然后必须从每个比赛中随机选择获胜者。
下面的解决方案假设每一行代表一个玩家,并且对于每一轮,第1行播放第2行,第3行播放第4行,等等。行数必须始终为2> = 2的幂(2, 4,8,16,32,64,......)
@echo off
setlocal enableDelayedExpansion
set "file=tournament.txt"
for /f %%C in ('find /c /v "" ^<"%file%"') do (
for /l %%N in (1 2 %%C) do (
set /p "p1="
set /p "p2="
set /a "1/(!random!%%2)" 2>nul&&echo !p1!||echo !p2!
)
) <"%file%" >"%file%.new"
move /y "%file%.new" "%file%" >nul
外部循环计算行数。内循环将奇数从1计数到计数,因此它精确迭代(行数除以2)次。内部循环的输入重定向到源文件,输出重定向到临时文件。
每个内循环迭代代表锦标赛中的游戏。 SET / P用于将玩家名称加载到变量中。然后将1除以模2的随机数,这将导致50%的时间除以0误差。错误消息被重定向到nul,然后使用条件运算符将一个或另一个播放器打印到输出文件。
完成循环后,将移动临时文件以替换原始文件。
答案 2 :(得分:0)
@echo off
setlocal enableextensions disabledelayedexpansion
set "inputFile=list.txt"
set "outputFile=remaining.txt"
set "odd=1"
>"%outputFile%" (
for /f "tokens=1,* delims=¬" %%a in ('
"cmd /q /v /e /c"
for /f "usebackq delims=" %%l in ("%inputFile%"^) do (
set /a 100000000+%random%*^!random^!^&echo(¬%%l
^)
""
^| sort /+3
') do if not defined odd ( set "odd=1" ) else (
echo %%b
set "odd="
)
)
type "%outputFile%"
这将获取输入文件,对于每一行,使用随机前缀回显其内容,使用随机数作为键对此列表进行排序,并从此列表中仅回显奇数行以输出文件。
已编辑我见过Aacini's answer,是的,输出的输出顺序与输入顺序相同。如果是这种情况,只需要另一个版本
@echo off
setlocal enableextensions disabledelayedexpansion
set "inputFile=list.txt"
set "outputFile=remaining.txt"
setlocal enabledelayedexpansion
rem Retrieve and calculate line limits to process
for /f %%a in ('^<"!inputFile!" find /c /v ""') do set /a "nLines=%%a", "nLimit=%%a/2"
rem Prepare an array with shuffled line numbers
for /l %%a in (1 1 %nlines%) do (
set /a "sel=!random! %% %%a + 1"
if !sel!==%%a ( set "r[%%a]=%%a" ) else (
for %%s in (!sel!) do set /a "r[%%a]=!r[%%s]!", "r[%%s]=%%a"
)
)
rem Read input file and output selected lines
<"!inputFile!" >"!outputFile!" (
for /l %%a in (1 1 %nLines%) do (
set /p "line=" || set "line="
if !r[%%a]! leq %nLimit% echo(!line!
)
)
type "!outputFile!"
答案 3 :(得分:0)
这是一个本机Windows批处理脚本,使用Jscript随机化文本文件的行并打印其中的一半。
文件的大小仅限于Jscript能够请求的RAM。
@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScript comment
:batch file portion
@echo off
if "%~1"=="" (
echo(Purpose: Randomises a text file - prints every 2nd random line
echo(
echo(Syntax: "%~0" "inputfile.txt" ^> "outputfile.txt"
echo(
pause
goto :EOF
)
:: Randomises a file
::
:: Reads the lines of file %1 into a jscript sparse array
:: with a random number and space before each line.
:: The array is sorted using the random numbers,
:: and the randomised lines are printed - prints every 2nd random line
@echo off
cscript //E:JScript //nologo "%~f0" %*
:pause
exit /b
************ JScript portion ***********/
e=0;
var array = new Array();
fso = new ActiveXObject("Scripting.FileSystemObject");
input=fso.OpenTextFile((WScript.Arguments(0)),1);
while (!input.AtEndOfStream) {
array[e]=Math.random()+" "+input.ReadLine();
e++;
}
input.close();
array.sort();
var re = new RegExp(".*? (.*)");
c=0;
while (c<e) {
var arr = re.exec(array[c])
if (c % 2) WScript.StdOut.Writeline(RegExp.$1);
c++;
}
答案 4 :(得分:0)
包含PowerShell解决方案以实现完整性。
$lines = Get-Content input.txt
$lines | foreach { $i=0 } {
[PSCustomObject]@{index=$i;line=$_}
$i++
} |
Get-Random -count ($lines.length / 2) |
sort index |
select -Expand line |
Set-Content output.txt
这将读取输入文件,并构建一个自定义对象数组,将文本与其行号相关联。该脚本使用Get-Random
来选择一半的行。 Get-Random不保留顺序,因此脚本会对原始行号进行排序。然后它按顺序提取原始行并将其写出来。
以上此脚本需要PowerShell 3.0才能使用PSCustomObject。版本3.0预装在Windows 7及更高版本上。如果您需要在Vista上运行,则可以改为使用PSObject,如this answer或this blog post所示。
请注意,如果换行符不重要,那么此脚本会变得更加简单。
$lines = Get-Content input.txt
$lines | Get-Random -count ($lines.length / 2) | Set-Content output.txt
要从批处理文件或CMD提示符运行PowerShell脚本,请使用以下命令。
powershell.exe -ex bypass -file yourscript.ps1
或者如果您的脚本完全适合一行,则无需创建单独的ps1
powershell.exe -c "$l = gc input.txt; $l | Get-Random -c ($l.length / 2) | sc output.txt"
答案 5 :(得分:0)
执行此操作的一种方法是为每个角色创建简单文件。然后使用随机脚本执行以下操作:
set/a number=%random% * (number of people there are) / 32768 + 1
set status=dead
call person%number%.bat (Each file should contain a set status=live script)
if %status% == live (
set/a peopletokill=%peopletokill%-1
del person%number%.bat
)
if %peopletokill% == 0 (
exit
)
这样的事情可行。