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%
)

これは、それぞれが独自に機能する2つの異なるコードですが、それらを組み合わせるのに問題があります。

以下のコードは、実行するたびにファイルからランダムな行を表示します。

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%*94バイトのsignedintの最大値を超えると、失敗する可能性があります。また、それがあなたが望む値の分布を与えているとは思いません。ランダムな行番号の場合と同じように、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 に答える