1. ホーム
  2. スクリプト・コラム
  3. DOS/BAT(ドス・バット

バッチ関数の効率的な代替アプリケーション(コールフリー)

2022-01-08 17:43:25

本格的なバッチ関数応用に高速でアプローチ! サブプロシージャを呼び出さない これでバッチプログラミングは次の段階に進むはずです。

現在、1つのパラメータのみサポートされており

@echo off
::Define functions
set "d-h=setlocal enabledelayedexpansion&set/a dx=#a#&set xs=0123456789abcdef&(for /l %%z in (1,1,4) do set /a x%%z=dx%%16,dx =dx/16)&(for /f "tokens=1-4" %%1 in ("!x1! !x2! !x3! !x4!") do set hx=!xs:~%4,1!!xs:~%3,1!&(if !hx!==00 set hx=)& amp;(for %%z in ("!hx!!xs:~%%2,1!!xs:~%%1,1!") do endlocal& set #a#=%%~z))"
::10 to hex function, parameter entry #a#
::To be defined before turning on variable delay
setlocal enabledelayedexpansion
for /l %%a in (1,7,1024) do (
    set abc=%%a
    
(%d-h:#a#=abc%)
rem function call

echo !abc!
)
pause

複数のパラメータに対応できるようになりました
len関数を2つのパラメータに対応させました。

@echo off

::Define functions
set "d-h=setlocal enabledelayedexpansion&set/a dx=#a#&set xs=0123456789abcdef&(for /l %%z in (1,1,4) do set /a x%%z=dx%%16,dx =dx/16)&(for /f "tokens=1-4" %%1 in ("!x1! !x2! !x3! !x4!") do set hx=!xs:~%4,1!!xs:~%3,1!&(if !hx!==00 set hx=)& amp;(for %%z in ("!hx!!xs:~%%2,1!!xs:~%%1,1!") do endlocal& set #a#=%%~z))"
::10 decimal to hexadecimal function, call method: %d-h:#a#=variable name%

set "len=for /f "tokens=1-3" %%1 in ("#a#") do setlocal enabledelayedexpansion&(if defined %%2 (set /a z=8180,x=0& amp;(for /l %%a in (1,1,14) do set/a "y=(z-x)/2+x"&(for %%b in (!y!) do if "! %%2:~%%b,1!" equ "" (set/a z=y) else (set/a x=y)))) else (set z=0))&(for %%z in ("!z!") do endlocal&set %%1=%%~z) "
::take the string length function, call method: %len:#a#=result variable name string variable name %
setlocal enabledelayedexpansion

for /l %%a in (1,7,1024) do (
    set abc=%%a

        (%len:#a#=slen abc%)
        (%d-h:#a#=abc%)
        (%len:#a#=dlen abc%)
        rem function calls
        
        echo %%a to hex as:!abc! Number of characters before conversion:!slen! Number of characters after conversion:!dlen!
)
pause

発想が実に新しい
しかし、次の2つの理由から推奨されません。
コードの可読性が低下する
環境変数の使いすぎも効率に影響する

機能効率に関する問題
従来の "goto pair" は、よりシンプルで自由で効率的だと思う。

一般的に

組合せ文(括弧で囲まれた文)での関数の使用は避けるべき
もし、複合的なトレードオフとして
の場合、結合文のループ数と再帰レベルが設計要件を満たしていることを確認する必要があります。

この方法は、関数の内部構造については可読性に劣るが、メインプログラムの可読性については非常に良い性能を発揮する

ご覧ください。
(%len:#a#=slen abc%)
関数 len が呼び出され、変数 abc の文字列の長さを計算し、その結果を変数 slen に格納します。

関数を使う意味は、メインプログラムを簡略化することではありませんか?
また、関数については、過去の関数や自分がよく使う関数コードの参照であることが多いので、コメントに従って使えばよいでしょう。
その関数が内部で何をやっているのか、わざわざ気にする必要もないでしょう。他のプログラミング言語でapiやdosの割り込みを呼び出すようなもので、内部で何が起こっているのか知る必要はないのでは?

このような関数があれば、バッチ処理の初心者でも簡単に効率的なバッチを書くことができますね。
これらは、ベテランがより大きなバッチプログラムを書きたいときでも、大きな煉瓦となる。
この関数定義はたった1行でできます。欠点は変数名と環境変数のスペースを取ることですが、これは効率を考えると微々たるものです。なぜなら :sub サブプロシージャの呼び出しは30階層もかかり、set var=n の300回の実行はもちろん、ポイントがあり、この使い方だと :sub バッチの内部サブルーチンを呼ぶより半分は速いですが、それでも %len:#a#=var% を使うより時間がかかりますから効率性は想像できますね。

関数のこのようなカプセル化した後、それはトークン%%aのための同じの使用にメインプログラム、len関数、メインプログラムと関数の4階の構造を破ることは不可能ですが、同じは、正しい結果を得ることができます。関数内の変数の使用は完全に一時的なもので、関数の終わりにendlocalでクリアされ、戻り値の結果のみを保存しています。

褒めたいことがあるんです、なかなか言いにくいんですが。ある創作で、ふとnetbentonのような関数の使い方を思い出したので、私も真似してみました、へへへ。確かに、オーナーの言うように、バッチ処理の機能を十分に拡張できるような、効率的で正しい、よく使われる関数を開発して、より高機能を蓄積し、その結果、より高い飛躍を実現することが必要です。

コマンドの繰り返し呼び出しに対応する方法・技術については、いくつかあるようです。
1. コピー&ペーストの繰り返し このパターンは、実行タスクやコマンドが比較的少ない場合に使えます。例えば、echoを使って2~3行の空行を生成するのは、forを使って費用対効果の高いものを生成するより良いのではないでしょうか? このパターンの結果、重複したコードが多くなり、効率も悪くなります。
2. タグ、GOTOジャンプを使う。最も基本的なパターンは、同じ関数セグメントを何度も使うコードからタグを作り、gotoを使ってジャンプすることです。しかし、gotoはあくまでジャンプアウトの役割であり、ジャンプバックの役割ではないので、コードを自動的に戻したい場合は、再度ジャンプする必要があります。
3.タグを使用して、callを呼び出す。callの利点は、他のタグにジャンプした後、自動的にジャンプバックできることである。なぜ自動的にジャンプバックできるかというと、callは元のコードの後にタグを使うので、元のプロセスを中断するためにメモリストレージを多く使用する可能性があるからです。そのため、比較的遅く感じられるでしょう。しかし、callは引数のサポートが充実しているので、手放せなくなるのです。
4. FORコマンドを使ってシンプルにする。FORの特徴に合ったコマンドをFORに組み込むことで、必要な繰り返し操作を減らすことができます。
5、変数を拡張するために関数を使用する。特定の変数にいくつかのコマンドの組み合わせを割り当てて、パラメータをサポートする汎用関数に変えると、ラベルを再作成する必要はありませんが、変数のスペースを占有します。このモードは、割り当てられたコマンドの組み合わせが短く、あまりスペースをとらない変数関数に適しています。また、異なるバッチプログラムで使用するために、簡単にラップすることができます。