73

私はcmd.exeで遊んでいましたが、そのヘルプでは、配列を定義する方法に関する情報が見つかりませんでした。

単純な変数を定義する方法を見つけました:

set a=10
echo %a%

でも、配列や連結リストなどを作りたい...

それで、cmd.exeでそれはできますか(つまり、cmd.exeには配列キーワードが存在しますか?)

いくつかのアルゴリズムを次のように実現したい:

  • バブルソート
  • クイックソート
  • ノームソート

等...

それで、私も知りたいのですが、Cmd.exeには参照やインスタンス、構造体などがありますか?

そのヘルプが完全ではない原因: /?

Cmd.exe は、Turing-Machine の定義で完全に定義されている可能性がありますか? ( チューリング完全 )

4

11 に答える 11

194

Ok。誤解のないように、できるだけわかりやすく説明します...

Windows バッチ ファイルでは、変数名は文字で始まる必要があり、任意の有効な文字を含めることができます。有効な文字は次のとおりです: #$'()*+,-.?@[]_`{}~ 文字と数字。

これは、cmd.exe の観点からは、SET NORMAL_NAME=123とまったく同じであり、また;SET A#$'()*+,-.?@[\]_{}~=123とも同じであることを意味します。SET VECTOR[1]=1233 つすべてが通常の変数です。このように、配列要素の形式で変数名を記述するのはあなた次第です。

set elem[1]=First element
set elem[2]=Second one
set elem[3]=The third one

このように、echo %elem[2]%表示されSecond oneます。

別の変数をインデックスとして使用する場合は、パーセント記号で囲まれた変数をその値で置き換えると、左から右に解析されることを知っておく必要があります。この意味は:

set i=2
echo %elem[%i%]%

は、変数の値を表示し、その後に を表示し、elem[その後に変数の値を表示することを意味するため、目的の結果が得られません。i]

この問題を解決するには、 Delayed Expansionを使用する必要があります。つまり、コマンドを先頭に挿入setlocal EnableDelayedExpansionし、インデックス変数をパーセント記号で囲み、配列要素を感嘆符で囲みます。

setlocal EnableDelayedExpansion
set elem[1]=First element
set elem[2]=Second one
set elem[3]=The third one
set i=2
echo !elem[%i%]!

FOR コマンドのパラメーターをインデックスとして使用することもできますfor /L %%i in (1,1,3) do echo !elem[%%i]!。!index! を使用する必要があります。FOR または IF: 内でインデックスが変更されたときに、配列要素に値を格納しますset elem[!index!]=New value。FOR/IF 内でインデックスが変更されたときに要素の値を取得するには、要素を 2 つのパーセント記号で囲み、コマンドの前にcall. たとえば、配列要素の範囲を左に 4 桁移動するには、次のようにします。

for /L %%i in (%start%,1,%end%) do (
   set /A j=%%i + 4
   call set elem[%%i]=%%elem[!j!]%%
)

前のプロセスを実現する別の方法は、追加の FOR コマンドを使用して、インデックスの遅延展開を同等の置換可能なパラメーターで変更し、配列要素に遅延展開を使用することです。このメソッドは、以前の CALL よりも高速に実行されます。

for /L %%i in (%start%,1,%end%) do (
   set /A j=%%i + 4
   for %%j in (!j!) do set elem[%%i]=!elem[%%j]!
)

このように、バッチ ファイルは配列を管理するように動作します。ここで重要なのは、Batch が配列を管理するかどうかではなく、他のプログラミング言語と同じように Batch ファイルで配列を管理できるということです。

@echo off
setlocal EnableDelayedExpansion

rem Create vector with names of days
set i=0
for %%d in (Sunday Monday Tuesday Wednesday Thrusday Friday Saturday) do (
   set /A i=i+1
   set day[!i!]=%%d
)

rem Get current date and calculate DayOfWeek
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
   set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
)
if %mm% lss 3 set /A mm=mm+12, yy=yy-1
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10, jdn=c+dd+e+f-1523, dow=jdn %% 7 + 1
echo Today is !day[%dow%]!, %date%

インデックス値は数値に限定されませんが、有効な文字を含む任意の文字列であることに注意してください。この点により、他のプログラミング言語で連想配列と呼ばれるものを定義できます。この回答には、連想配列を使用して問題を解決するために使用される方法の詳細な説明があります。また、スペースは変数名に有効な文字であるため、変数名にスペースを挿入しないように注意する必要があります。

この投稿で、バッチ ファイルで配列表記を使用する必要がある理由について詳しく説明しました。

この投稿には、テキスト ファイルを読み取り、行のインデックスをベクターに格納し、行の内容に基づいてベクター要素のビューブル ソートを実行するバッチ ファイルがあります。同等の結果は、ファイルの内容の並べ替えです。

この投稿では、ファイルに格納されたインデックスに基づく Batch の基本的なリレーショナル データベース アプリケーションがあります。

この投稿では、サブディレクトリから取得した大きなデータ構造を組み立てて、TREE コマンドの形式で表示する、完全な複数連結リスト アプリケーションを Batch で作成しています。

于 2012-04-16T02:15:34.890 に答える
8

Windows シェル スクリプトは、複雑なデータ構造はおろか、配列を操作するようには設計されていません。ほとんどの場合、Windows シェルではすべてが文字列ですが、ループを使用してn変数を宣言し、プレフィックスでフィルター処理する、または区切り文字列を作成してから区切られた文字列を反復処理する構造。VAR_1, VAR_2, VAR_3...VAR_FOR

ITEM_NAME, ITEM_DATA同様に、同じ基本的な考え方を使用して、または w/eのような構造体のような変数のセットを作成できます。CMD での連想配列のシミュレートについて説明しているこのリンクも見つけました。

結局のところ、それはすべてひどくハックで不便です。コマンドライン シェルは、負荷の高いプログラミング用に設計されていません。@MatteoItalia に同意します。本格的なスクリプトが必要な場合は、実際のスクリプト言語を使用してください。

于 2012-04-15T22:01:21.767 に答える
7

少し前に、疑似配列を使用してバッチでバブルソートの実装を作成しました。リストのサイズが大きくなるにつれてかなり遅くなるため、なぜそれを使用するのかわかりません(ただし、別のバッチファイルで使用することは認めます)。それは自分自身に少しの挑戦を設定することでした。 誰かがこれを便利だと思うかもしれません。

:: Bubblesort
:: Horribly inefficient for large lists
:: Dave Johnson implementation 05/04/2013
@echo off
setlocal enabledelayedexpansion
:: Number of entries to populate and sort
set maxvalue=50
:: Fill a list of vars with Random numbers and print them
for /l %%a in (1,1,%maxvalue%) do (
    set /a tosort%%a=!random!
)
:: echo them
set tosort
:: Commence bubble sort
Echo Sorting...
set /a maxvalue-=1
set iterations=0
for /l %%a in (%maxvalue%,-1,1) do ( REM Decrease by 1 the number of checks each time as the top value will always float to the end
    set hasswapped=0
        for /l %%b in (1,1,%%a) do (
            set /a next=%%b+1
            set next=tosort!next!
            set next=!next!
            call :grabvalues tosort%%b !next!
            rem echo comparing tosort%%b = !tosortvalue! and !next! = !nextvalue!
            if !nextvalue! LSS !tosortvalue! (
            rem set /a num_of_swaps+=1
            rem echo Swapping !num_of_swaps!
                set !next!=!tosortvalue!
                set tosort%%b=!nextvalue!
                set /a hasswapped+=1
            )
        )
    set /a iterations+=1
    if !hasswapped!==0 goto sorted
)
goto:eof
:grabvalues
set tosortvalue=!%1!
set nextvalue=!%2!
goto:eof
:sorted
::nice one our kid
set tosortvalue=
echo Iterations required: %iterations%
set tosort
endlocal
于 2014-03-05T10:14:53.740 に答える
5

真剣に言えば、バッチに配列があるとは聞いたことがありません。奇妙なトリックでそれらをエミュレートできるかもしれませんが、それは良い考えとは言えません。

参照/インスタンス/構造体は実際の言語用のものです。cmd スクリプトは、command.com である非常に原始的なインタープリター上で成長した一連の拡張機能にすぎません。基本的なスクリプトを実行できますが、一連の呼び出しよりも複雑なことは何でも実行できます。他のコマンドは、見苦しく、理解不能になる運命にあります。

唯一の「高度な」コンストラクトは、すべてforを行う奇妙なループであり、変数置換の奇妙な「ルール」 ( %var%%%var!var!はばかげたパーサーのために異なるものです) と混ざり合って、些細なアルゴリズムを書くことさえ、奇妙なハック (たとえば、クイックソートの実装については、こちらを参照してください)。

私のヒントは、スクリプトを適切な方法で作成したい場合は、実際のスクリプト言語を使用し、単純で迅速なハックと下位互換性のためにバッチを残すことです。

于 2012-04-15T21:54:58.850 に答える
-4
@echo off

set array=

setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

set nl=^&echo(

set array=auto blue ^!nl!^
  bycicle green ^!nl!^
  buggy   red

echo convert the String in indexed arrays

set /a index=0

for /F "tokens=1,2,3*" %%a in ( 'echo(!array!' ) do (

 echo(vehicle[!index!]=%%a color[!index!]=%%b 
 set vehicle[!index!]=%%a
 set color[!index!]=%%b
 set /a index=!index!+1   

)

echo use the arrays

echo(%vehicle[1]% %color[1]%
echo oder

set index=1
echo(!vehicle[%index%]! !color[%index%]!
于 2016-11-02T10:21:55.227 に答える