15

forループを使用せずに、文字列を2つの部分に分割したいと思います。

たとえば、変数に文字列があります。

str=45:abc

45変数とabc別の変数を取得したい。バッチファイルで可能ですか?

パターンはsomenumber:somestringのようなものです

4

6 に答える 6

18

strをさまざまな方法で分割できます。

forループは、使用したくありません。

末尾の部分は簡単*です(...まで何でも一致します)
set "var2=%str:*:=%"

主要な部分は厄介なトリックで行うことができます
set "var1=%str::="^&REM #%

アンパサンドをエスケープするにはカレットが必要な
ので、実質的にコロンは次のように置き換えられ"&REM # ます。あなたの場合、置き換え後に行を取得します。
set "var1=4567"&REM #abcde
これは2つのコマンドに分割されます 。

set "var1=4567"
REM #abcde` 

そして完全なコードはここにあります:

set "str=4567:abcde"
echo %str%
set "var1=%str::="^&REM #%
set "var2=%str:*:=%"
echo var1=%var1% var2=%var2%

編集2:より安定した先頭部分

ラインフィードを使用するアイデアをくれたDaveに感謝します。
REMテクニックは、引用符や特殊文字を含むコンテンツに対してあまり安定していません。
しかし、改行のトリックを使用すると、分割引数が1文字より長い場合にも機能する、より安定したバージョンが存在します。

@echo off
setlocal enableDelayedExpansion
set ^"str=456789#$#abc"
for /F "delims=" %%a in (^"!str:#$#^=^

!^") do (
  set "lead=%%a"
  goto :break
)
:break
echo !lead!

解決策3:適応されたdbenhamsの答え

Dbenhamは、彼のソリューションでパイプ付きのラインフィードを使用しています。
これは少し複雑に思えます。
解決策は事実を使用しているため、パーサーはエスケープされていない改行の後に残りの行を削除します(これが特殊文字フェーズの前またはフェーズで見つかった場合)。

最初に、コロン文字は遅延拡張置換を使用して改行に置き換えられます。
これは許可されており、改行は変数の一部になっています。
次に、線set lead=%lead%は後続部分を取り除きます。引用符が文字列の一部である場合は壊れてしまうため
、ここでは拡張構文を使用しないことをお勧めします。set "lead=%lead%"

setlocal enableDelayedExpansion
set "str=45:abc"
set ^"lead=!str::=^

!"
set lead=%lead%
echo "!lead!"
于 2013-01-31T08:52:05.837 に答える
4

これを試すことができます。固定されている場合、コロンの左側の数値は常に2になり、右側の数値は3になります。次に、strに値があると仮定すると、次のコードが機能するはずです。

set "str=45:abc"
echo %str%
set var1=%str:~0,2%
set var2=%str:~3,3%
echo %var1% %var2%

投稿してください。:)

于 2013-01-31T07:52:44.913 に答える
3

FORループの使用を避けるのは無意味に思えますが、問題は興味深いものになります。

jebが指摘しているように、末尾の部分を取得するのは簡単!str:*:=!です。

トリッキーなビットが主要な部分です。これがjebのソリューションの代替案です。

:次の構文を使用する代わりに、変数に改行を挿入できます

setlocal enableDelayedExpansion
set "str=45:abc"
echo !str::=^

!

- 出力 -

45
abc

最後の上の空の行!は重要です。

理由はわかりませんが、上記の出力をコマンドにパイプすると、最初の行だけが保持されます。したがって、出力を任意の行に一致するFINDSTRにパイプ処理し、その結果をファイルに送信して、SET/Pを使用して変数に読み込むことができます。

<LF>SET / Pはラインターミネータとして認識しないため、SET / Pを使用する前に2行目を削除する必要があります。これは、を認識するだけ<CR><LF>です。

完全な解決策は次のとおりです。

@echo off
setlocal enableDelayedExpansion
set "str=45:abc"
echo(!str::=^

!|findstr "^" >test.tmp
<test.tmp set /p "var1="
del test.tmp
set "var2=!str:*:=!"
echo var1=!var1!  var2=!var2!

アップデート

私は、2行目が出力から削除される理由をほぼ理解したと思います:)

これは、パイプがWindows cmd.exeによって処理され、各側が新しいCMD.EXEスレッドによって処理される方法と関係があります。パイプされたコードブロック内で遅延拡張が失敗するのはなぜですか?を参照してください。jebからの素晴らしい答えのある関連する質問のために。

パイプされたコマンドの左側を見ると、(メモリ内で)次のようなステートメントに解析されていると思います。

C:\Windows\system32\cmd.exe /S /D /c" echo {delayedExpansionExpression}"

{delayedExpansionExpression}は複数行の検索を表し、まだ発生していない拡張を置き換えるために使用します。

次に、変数式が実際に展開され、検索と置換によって行が2つに分割されると思います。

C:\Windows\system32\cmd.exe /S /D /c" echo 43
abc"

その場合にのみコマンドが実行され、通常のcmd.exeルールでは、コマンドは改行で終了します。引用符で囲まれたコマンド文字列に終了引用符がありませんが、パーサーはそれを気にしません。

私がまだ困惑しているのは、どうなるかということabc"です。実行しようとすると、「abc」のようなエラーメッセージが内部または外部コマンド、操作可能なプログラム、またはバッチファイルとして認識されないという結果になると思いましたが、代わりに、エーテル。

注-jebの3番目のコメントは理由を説明しています:)


FORなしの安全なバージョン

私の元のソリューションは、のような文字列では機能しませんthis & that:cats & dogs。これは、文字列の長さの制限と末尾の制御文字が先頭部分から削除されることを除いて、ほぼすべての文字列で機能するFORなしのバリエーションです。

@echo off
setlocal enableDelayedExpansion
set "str=this & that:cats & dogs"
set ^"str2=!str::=^

!^"
cmd /v:on /c echo ^^!str2^^!|findstr /v "$" >test.tmp
<test.tmp set /p "var1="
del test.tmp
set "var2=!str:*:=!"
echo var1=!var1!  var2=!var2!

新しいCMDスレッドまで拡張を遅らせ、 。$で終わる行にのみ一致するFINDSTR正規表現の癖を使用し<cr>ます。最初の行にはそれがなく、2番目の行にはあります。この/vオプションは結果を反転します。

于 2013-06-13T22:41:28.457 に答える
3

はい、私はこれが非常に古いトピックであることを知っていますが、私はそれを発見したばかりであり、私の解決策を投稿する誘惑に抵抗することはできません:

@echo off
setlocal

set "str=45:abc"
set "var1=%str::=" & set "var2=%"
echo var1="%var1%"  var2="%var2%"

この方法の詳細については、こちらをご覧ください

于 2015-06-07T00:08:22.433 に答える
0

これは、主要な部分のための厄介なトリックのない解決策です

    REM accepts userID@host
    setlocal enableDelayedExpansion
    set "str=%1"
    set "host=%str:*@=%"
    for /F "tokens=1 delims=@" %%F IN ("%str%") do set "user=%%F"
    echo user@host = %user%@%host%
    endlocal
于 2015-07-06T20:47:02.980 に答える
0

ここで変数を分割するためのあらゆる種類のメソットを投稿する人々に照らして、私は自分のメソッドを投稿することもできます。これにより、同じ記号で示される変数から1つだけでなく、複数の分割が可能になります。これはREMでは不可能です。メソッド(私はしばらくの間使用しました、@ jebに感謝します)。

以下の方法では、2行目で定義された文字列が3つの部分に分割されます。

setlocal EnableDelayedExpansion
set fulline=one/two/three or/more
set fulline=%fulline%//
REM above line prevents unexpected results when input string has less than two /

set line2=%fulline:*/=%
set line3=%line2:*/=%

set line1=!fulline:/%line2%=!
set line2=!line2:/%line3%=!

setlocal DisableDelayedExpansion

echo."%line1%"
echo."%line2%"
echo."%line3%"

出力:

"one"
"two"
"three or/more//"

文字列の最後に作成されたパーティションを、残りの「安全」分割文字の「ビン」として使用することをお勧めします。

于 2015-07-27T10:35:57.020 に答える