2

文字列を分割するにはどうすればよいですか

"   This  is  a text  with  spaces    "

スペースを失うことなく、変数「文字列」をテキスト部分に変換しますか?

set string="#   This  is  a text  with  spaces    #"

に分割する必要があります

"#   This"
"  is"
"  a"
" text"
"  with"
"  spaces    #"

すべてのスペースを削除するため、使用 For /F "delims= " ... は機能しません。

「単純な」解決策はありますか、または文字列を文字ごとに解析する方法を誰かが説明できるので、最初の文字までスペースを数え、次のスペースまですべての文字を読み取り、カウントされたスペースと読み取った文字を一緒に new/一時変数 ??

ありがとう

4

5 に答える 5

3

ええ、どちらもよくわかりません#後続のスペースを保持する「スペース #」について、他のすべての要素は前のスペースを保持しますが、先行するスペースは保持しませんか?

ええと、質問に費やされた努力 = 答えるために費やされた努力。これであなたがすることをしてください。

@if (@a==@b) @end /*

:: batch portion

@echo off
setlocal

call :split "#   This  is  a text  with  spaces    #"
exit /b

:split <string>
cscript /nologo /e:jscript "%~f0" "%~1"
goto :EOF

:: JScript portion */
WSH.Echo(WSH.Arguments(0).match(/\s*\S+/g).join('\n'));

出力:

#
   This
  is
  a
 text
  with
  spaces
    #

アップデート

最初の要素と 2 番目の要素、および最後から 2 番目の要素と最後の要素を結合する場合は、上記のスクリプトの JScript 部分を次のように変更します。

:: JScript portion */
var m = WSH.Arguments(0).match(/\s*\S+/g);
m[0] = m.shift() + m[0];
m[m.length - 2] += m.pop();
WSH.Echo(m.join('\n'));

出力:

#   This
  is
  a
 text
  with
  spaces    #

各要素を引用符で囲む場合は、最後の行を次のように変更します。

    WSH.Echo('"' + m.join('"\n"') + '"');

出力:

"#   This"
"  is"
"  a"
" text"
"  with"
"  spaces    #"
于 2013-04-17T20:27:09.253 に答える
2

トリックは、連続するスペースを 1 つのスペースだけに置き換え、残りを任意の文字に置き換えることです。文字列に s が含まれておらず、連続するスペースが 9 つ以下であると仮定すると、#これを試すことができます

set st=%st:         = ########%
set st=%st:        = #######%
set st=%st:       = ######%
set st=%st:      = #####%
set st=%st:     = ####%
set st=%st:    = ###%
set st=%st:   = ##%
set st=%st:  = #%

次に、 を解析してスペースfor /fで置き換えることができます#

setlocal enabledelayedexpansion
for /f %%a in ("%st%") do (
  set ss= %%a
  echo !ss:#= !
)  

括弧ブロック内では、遅延展開を有効にし、構文setを使用する必要があることに注意してください (「 」を参照)!HELP SET

ただし、この手法では最初の部分文字列のみが抽出されます。一般化するには、別のトリックが必要です。つまり、スペースを改行に置き換えて、for /f行ごとにループするようにします

set改行文字を取得するには、コマンドの後に 2 つの空白行を保持する必要があることに注意してください。

set nl=^


rem continue two lines down....
for /f %%a in ("%st: =!nl!%") do (
  set ss= %%a
  set ss=!ss:#= !
  echo [!ss!]
)  
于 2013-04-17T16:53:10.903 に答える
2

I don't see a simple solution in batch, though of course if you can consider powershell or javascript you'll be working with a more appropriate toolset for string manipulation.

Sticking with the batch requirement, you can loop through character by character and "collect" your words with something like this:

@echo off
setlocal enabledelayedexpansion

set "string=   This  is  a text  with  spaces    "

set idx=0
set "word="
set "char="
set "lastchar= "
:loop
if "!string:~%idx%!" equ "" goto :eof
set char=!string:~%idx%,1!
if "%char%" equ " " (
    if "%lastchar%" neq " " (
        echo [%word%]
        set word=%char%
    ) else (
        set word=%word%%char%
    )
) else (
    set word=%word%%char%
)
set lastchar=%char%
set /a idx=%idx%+1
goto loop

This script uses batch's substring feature !string:~%idx%,1 to grab a single character from the string, incrementing idx with each loop. Then it's just a matter of processing the word (echo in this example) when the previous character was not a space and the current one is.

This writes out:

[   This]
[  is]
[  a]
[ text]
[  with]
[  spaces]

Note that I'm ignoring the # you had in your example because I don't understand where they fit in.

于 2013-04-17T16:28:02.493 に答える
2

このあいまいなタスクを達成する必要がある場合は、rojo's answer のようなハイブリッド JScript/バッチ手法を使用します。ただし、既に作成した REPL.BAT ユーティリティを使用します。REPL.BAT が現在のフォルダーまたは PATH のどこかにあると仮定すると、次のように動作します。

@echo off
setlocal enableDelayedExpansion
set "string=#   This  is  a text  with  spaces    #"

:: Build an "array" of text parts
set cnt=0
for /f delims^=^ eol^= %%A in ('repl "([^ ])(?= )" "$1\n" xs string') do (
  set /a cnt+=1
  set "string!cnt!=%%A"
)

:: Print the array values
for /l %%N in (1 1 %cnt%) do echo string%%N=[!string%%N!]

しかし、純粋なバッチ ソリューションが必要な場合は、以下のかなり効率的な方法を使用します。

@echo off
setlocal enableDelayedExpansion
set "string=#   This  is  a text  with  spaces    #"

:: Define LF to contain a single line feed character (0x0A)
set LF=^


:: Above 2 blank lines are critical - DO NOT REMOVE


:: Insert a line feed before every space
for %%n in ("!LF!") do set "string=!string: =%%~n !"

:loop  Remove line feeds sandwiched by spaces
for %%n in ("!LF!") do set "string2=!string: %%~n =  !"
if "!string2!" neq "!string!" (
  set "string=!string2!"
  goto :loop
)

:: Build an "array" of text parts: FOR /F splits the string at line feeds
set /a cnt=0
for /f delims^=^ eol^= %%A in ("!string!") do (
  set /a cnt+=1
  set "string!cnt!=%%A"
)

:: Print out the array values
for /l %%N in (1 1 %cnt%) do echo string%%N=[!string%%N!]

上記の両方のソリューションでは、次の出力が得られます。

string1=[#]
string2=[   This]
string3=[  is]
string4=[  a]
string5=[ text]
string6=[  with]
string7=[  spaces]
string8=[    #]

%%A文字列!に遅延展開が含まれている場合、FOR ループ展開によって結果が破損することに注意してください。この制限は、コーディングを追加することで解消できます。FOR ループを使用する他のすべての投稿されたソリューションには、この同じ制限があります。(少なくとも私がこれを書いたときはそうでした)

于 2013-04-18T00:14:26.900 に答える
2

これを試して:

@echo off &setlocal enabledelayedexpansion
set "string=#   This  is  a text  with  spaces    #"

set string1=%string%
for %%i in (%string%) do (
    set string1=!string1: %%i = "%%i" !
    set /a strings+=1
)
set string1=#"%string1:~1,-1%"#
set string1=%string1:"= "%
for %%i in (%string1%) do (
    set /a count+=1
    set string2=%%i
    set string2=!string2: "=!
    set string2=!string2:"=!
    if !count! equ 2 (
     set $s1=!$s1!!string2!
    )else if !count! equ %strings% (
        set /a count-=1
        call set $s!count!=%%$s!count!%%!string2!
        ) else set $s!count!=!string2!
)
for /f "tokens=1*delims==" %%i in ('set "$s"') do echo "%%j"    

出力:

"#   This"
"  is"
"  a"
" text"
"  with"
"  spaces    #"
于 2013-04-17T17:32:13.563 に答える