我有这个脚本,要读取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)我们可以使用这个:
SET LF=^
setlocal EnableDelayedExpansion
... (next code) ...
set "var=!var: =%LF%!"
因此,当没有延迟的LF变量时,我们可以嵌入它。或者不是?
和2)为什么在你的代码中
for %%L in ("!LF!") do set "X=!X: =%%~L!"
你使用%% ~L而不仅仅是%% L
答案 0 :(得分:1)
您当前的问题是FOR / F不会在一行中迭代令牌。它只是解析您要求的每个令牌。如果你没有指定“标记”选项,那么它默认为“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!"
关于你的代码我不明白的一件事 - 你的初始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将换行符视为行分隔符并迭代每一行,因此不会保留换行符。