0

私はxmlファイルを読むためにこのスクリプトを持っています。ファイルには座標が含まれており、座標を一覧表示したい:

@echo off
setlocal EnableDelayedExpansion

FOR %%K IN (*.xml) DO (
SET K=%%K
SET K=!K:~0,-4!
SET "prep=0"

    REM READ DATA
    FOR /F "tokens=*" %%X IN (!K!.kml) DO (
    if !prep! == 1 (
    echo %%X
    pause
      FOR /F %%L IN ("%%X") DO (
      SET L=%%L
      IF NOT "!L:~0,1!" == "<" (
        echo %%L
        )       
      )
      SET "prep=0"
    )
    if "%%X" == "<coordinates>" ( SET "prep=1" )
    )
)

私はこれらの結果を得ました:

14.63778004128814,49.50141683426452,0 14.63696238385996,49.48348965654706,0 14.6
8840586504191,49.47901033971912,0 14.68589371304878,49.49939179836829,0 14.63778
004128814,49.50141683426452,0 </coordinates>
Press and key to continue...
14.63778004128814,49.50141683426452,0
Press and key to continue...

最初に、座標付きの線が表示されます。次に、3 番目のループで、座標が出力されます。しかし、印刷された座標は 1 組しかありません...もう一度キーを押すと、バッチは次の列を印刷せずに終了します。手伝ってくれますか?

編集 回答が投稿された後、質問があります1)これを使用できますか:

SET LF=^


setlocal EnableDelayedExpansion
... (next code) ...
set "var=!var: =%LF%!"    

したがって、遅延した LF 変数がない場合は、それを埋め込むことができます。か否か?

そして2)なぜあなたのコードで

for %%L in ("!LF!") do set "X=!X: =%%~L!"

%%L だけでなく、%%~L を使用しましたか

4

1 に答える 1

1

当面の問題は、 FOR /F が行内のトークンを反復しないことです。要求する各トークンを単純に解析します。「tokens」オプションを指定しない場合、デフォルトで「tokens=1」になり、行の最初のトークンのみが解析されます。

ただし、文字列に改行文字が含まれている場合、FOR /F は文字列を複数の行として扱います。その後、必要に応じて各行を繰り返します。トリックは、スペース区切り文字を改行文字に置き換えることです。いくつかの方法がありますが、私が最も使いやすいと思われる方法を紹介します。

最初に単一の改行を含む変数を定義します

set LF=^


::The two blank lines above are critical for the definition of the line feed

次のトリックは、変数内のスペースを改行に置き換えることです。通常、置換に変数を使用した置換は のようになりますset "var=!var:search=%replaceVar%!"。しかし、それは LF 変数では機能しません。通常の展開を使用して LF 変数を操作するのは困難です。遅延展開を使用する方がはるかに簡単です。遅延拡張内に遅延拡張を埋め込むことはできませんが、LF の値を単純な FOR 変数に転送して使用することはできます。for %%L in ("!LF!") do set "var=!var: =%%~L!"

あなたのコードについて私が理解していないことの1つは、最初のFORループがすべての.KMLファイルで繰り返されていることです。部分文字列操作を使用して拡張子を取り除きます。環境変数を使用せずにこれを行うためのはるかに簡単な方法があり%%~nKます。拡張子なしでファイルのベース名を指定します。しかし、振り返って拡張子を再度追加するときに、なぜそれを行うのでしょうか?

%%K 値を直接使用しました - USEBACKQ オプションを追加し、ファイル名にスペースを許可するために引用符を追加しました。

これは、期待どおりに動作するコードです。

@echo off
setlocal EnableDelayedExpansion

::define a variable containing a linefeed character
set LF=^


::Above 2 blank lines are part of the LF definition, do not remove

for %%K in (*.kml) do (
  set "prep=0"
  for /f "usebackq tokens=*" %%X in ("%%K") do (
    if !prep! == 1 (
      echo %%X
      pause
      set "ln=%%X"
      for %%L in ("!LF!") do set "ln=!ln: =%%~L!"
      for /f %%L in ("!ln!") do (
        set L=%%L
        if not "!L:~0,1!" == "<" (
          echo %%L
        )
      )
      set "prep=0"
    )
    if "%%X" == "<coordinates>" ( set "prep=1" )
  )
)

しかし - もっと大きな問題があると思います。バッチを使用して XML を解析することで、苦痛の世界に身を置くことになるのではないかと心配しています。XML は常に同じようにレイアウトされると想定しています。改行や空白を XML 文書に追加または削除する有効な方法は無数にあり、アルゴリズムを壊してしまいます。すべての入力ファイルが同じソースから取得され、常に期待どおりにフォーマットされることを確認できますか? XSLT を使用して XML ドキュメントを解析し、座標のネイキッド リストに変換する必要があると思います。

追加の質問への回答

1)set "var=!var: =%LF%!"動作しません - LF の通常の展開には、エスケープ シーケンスと複数の展開が必要です。これはうまくいきます:set "var=!var: =^%LF%LF%!"

%LF% のエスケープ シーケンスは非常に複雑になる可能性があるため、回避するようにしています。

2) についてfor %%L in ("!LF!") do set "X=!X: =%%~L!"は、FOR /F ではなく単純な FOR であることに注意してください。!LF! そうしないと、FOR はそれを読み取りません。ただし、FOR ステートメントは (FOR /F とは異なり) 引用符を保持するため、囲んでいる引用符を削除するには %%~L が必要です。

改行に関して、FOR と FOR /F の間には非常に重要な違いがあります。FOR は引用符で囲まれた改行を保持しますが、FOR /F は改行を行区切り記号として扱い、各行を繰り返すため、改行は保持されません。

于 2012-04-07T13:31:19.563 に答える