call /?
から、~
in 変数 (例%~d1
) はファイル パス (ここではドライバ) の一部を解析するために使用されますが、チルダはここでは別のコンテキストで使用されていることがわかります。https://www.tutorialspoint.com/batch_script/batch_script_string_length.htm:
@echo off
set str = Hello World
call :strLen str strlen
echo String is %strlen% characters long
exit /b
:strLen
setlocal enabledelayedexpansion
:strLen_Loop
if not "!%1:~%len%!"=="" set /A len+=1 & goto :strLen_Loop
(endlocal & set %2=%len%)
goto :eof
ここで、この変数の展開の意味は何でしょうか。また、空の文字列と比較して文字列の長さをどのように計算するのでしょうか。ここでのチルダの目的は何でしょうか。さらに、この例では、出力がある場所(数値が増加する場所)"!%1:~%len%!"
で無限ループに陥ってしまいます。if not "!str:~136!" == "" set /A len+=1 & goto :strLen_Loop
!str:~n
答え1
チルダ (~) 記号はバッチ ファイル内でさまざまな方法で使用されます。
引数の引用符の削除。コマンドライン引数の前のチルダ記号 ("%~1" など) は、パラメータから周囲の引用符を削除することを示します。たとえば、%1 の値が "Hi" の場合、%~1 は Hi のみに展開されます。
部分文字列処理。バッチ ファイルで文字列変数から部分文字列を抽出する方法があります。構文は次のとおりです。
%variable:~num_chars_skip,num_chars_keep%
スキップする文字数は、文字列の開始位置、または文字列変数の前の文字数を除外する位置を意味します。保持する文字数は、開始位置の後の文字数を示します。保持する文字数はオプションですが、最初の文字は必須です。保持する文字数が指定されていない場合は、保持する文字数番目の文字のみが解析されます。
詳しいヘルプについては、コマンド プロンプトで以下をお読みください。
call /?
for /?
set /?
お役に立てれば幸いです
答え2
試すset /?
:
...
環境変数の置換が次のように強化されました。%PATH:str1=str2%
PATH 環境変数を展開し、展開された結果の "str1" の各出現を "str2" に置き換えます。展開された出力から "str1" のすべての出現を効果的に削除するには、"str2" を空の文字列にすることができます。"str1" はアスタリスクで始まることができ、その場合、展開された出力の先頭から str1 の残りの部分の最初の出現までのすべてに一致します。
拡張のための部分文字列を指定することもできます。
%PATH:~10,5%
PATH 環境変数を展開し、展開された結果の 11 番目 (オフセット 10) の文字から始まる 5 文字のみを使用します。長さが指定されていない場合は、変数値の残りがデフォルトになります。いずれかの数値 (オフセットまたは長さ) が負の場合、使用される数値は、指定されたオフセットまたは長さに環境変数値の長さを加えた値になります。
%PATH:~-10%
PATH 変数の最後の 10 文字を抽出します。
%PATH:~0,-2%
PATH 変数の最後の 2 文字を除くすべてを抽出します
。...
の行動非常に便利ですが、説明負の数についての誤解は紛らわしく不正確です。最初の数(オフセット)については正しいです。%VAR:~N%
末尾からN
文字を引いた数から始まります。2番数値の場合、それはもはや部分文字列ではない長さ、しかし、何文字目まで停止するかとして解釈される。価値、長さに関係なく。したがって、%VAR:~1,-1%
最初と最後の文字を除いた値を与え、と の両方%VAR:~-2,-1%
が%VAR:~-2,1%
最後から 2 番目の文字を与えます。
答え3
- このチュートリアルのコードを「修正」し、ループが無限にならないようにするには、コメントで引用されているとおりです。
わかりましたが、私のマシンでは、終了するには ^C が必要です。136 文字の長さや単語がないのに、136 という大きな数字が返されるのを見てください。- @牧者
@echo off && setlocal enabledelayedexpansion
set "_str=Hello World" & call :strLen_Loop str
:strLen_Loop
if "%~1" == "" (
endlocal & goto :EOF
) else if not "!_%~1:~%_len%!" == "" (
set /A "_len+=1" & goto=:strLen_Loop
) else echo\String is !_len! characters long & exit /b