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...

首先,您会看到带有坐标的线。其次,在第三个循环中,打印了坐标。但是我只打印了一对坐标...如果我再次按下一个键,则批处理完成而不打印下一列。你能帮我吗?

编辑 发布答案后,我有问题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”——它只解析行中的第一个token。

但是,如果字符串包含换行符,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!"

关于您的代码的一件事我不明白 - 您的初始 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,而不是 FOR /F。!LF!必须引用,否则 FOR 不会读取它。但是 FOR 语句保留了引号(与 FOR /F 不同),所以我需要 %%~L 来删除封闭的引号。

FOR 和 FOR /F 在换行方面有一个非常重要的区别。FOR 将保留引用的换行符,而 FOR /F 将换行符视为行分隔符并迭代每一行,因此不保留换行符。

于 2012-04-07T13:31:19.563 回答