【问题标题】:Multiline text file, how to put into an environment variable多行文本文件,如何放入环境变量
【发布时间】:2012-05-23 09:04:37
【问题描述】:

我有一个名为 file.txt 的文件,其中包含:

     this is line one ^
     this is line two ^
     this is the last line

我怎样才能把它放到一个环境变量中?

我可以从批处理文件中做到这一点: test.bat

    set LF=^
    [blank line]
    [blank line]
    rem two blank lines needed above
    set multi=Line 1!LF!Line 2!LF!Last line
    echo !multi!

这会输出三行:

      Line 1
      Line 2
      Last line

那么我怎样才能将 file.txt 放入批处理文件中的 envvar 中?

【问题讨论】:

  • 克拉 ^ 真的在文件中,还是 CRLF 的占位符?我假设这是一台 Windows 机器。
  • 插入符号确实在文件中,它是创建包含一个换行符的变量的方法。 set LF=^ 后跟两个空行
  • 感谢 jeb 的澄清
  • 是的 rob,这是一台 windows 机器。

标签: batch-file multiline


【解决方案1】:

你快到了。您需要阅读每一行文本,然后将行加上换行符附加到变量中。

可以使用FOR /F,但是如果内容包含! 字符,它就不能很好地处理延迟扩展。保留空白行也很尴尬,禁用 EOL 选项也很尴尬。

更简单的解决方案是使用 SET /P 读取行。这种技术的局限性在于:

1) 修剪每一行的尾随控制字符

2) 文件必须使用 Windows 标准的回车换行符。它不适用于 Unix 样式的换行符。

3) 限制为每行读取1023字节(不包括行终止符)

请记住,环境变量只能容纳不到 8 KB 的数据。因此,您只能使用这种技术将非常小的文件加载到变量中。

@echo off
setlocal enableDelayedExpansion
set LF=^


:: Two blank lines above needed for definition of LF - do not remove
set file="test.txt"
set "var="
for /f %%N in ('find /c /v "" ^<%file%') do set lineCnt=%%N
<%file% (
  for /l %%N in (1 1 %lineCnt%) do (
    set "ln="
    set /p "ln="
    set "var=!var!!ln!!lf!"
  )
)
set var

【讨论】:

  • +1,因为这是最简单的方法,在大多数情况下你不需要更多
  • 好吧,我认为我可能会用这个来突破限制,因为我的文件有时会超过 8k,所以我必须将一个文件解析为两个或多个变量..所以我会去 DOSville尝试不可能的事情:)
【解决方案2】:

正如 dbenham 所说,也可以使用 for/f 来完成,但要复杂一些。

简单的 80% 解决方案是

setlocal EnableDelayedExpansion

set "var="
set LF=^


rem *** Two empty lines are required for the linefeed
FOR /F "delims=" %%a in (myFile.txt) do (
  set "var=!var!!LF!%%a"
)
echo !var!

但它失败了:
- 如果一行是空白的,它将被跳过
- 如果一行以; EOL 字符开头
- 如果一行包含!(和插入符号)

但是你可以使用更复杂的解决方案

@echo off
SETLOCAL DisableDelayedExpansion
set "all="
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ aux1.txt"`) do (
    set "line=%%a"
    SETLOCAL EnableDelayedExpansion
    set "line=!line:#=#S!"
    set "line=!line:*:=!"
    for /F "delims=" %%p in ("!all!#L!line!") do (
        ENDLOCAL
        set "all=%%p"
    )
)
SETLOCAL EnableDelayedExpansion
if defined all (
set "all=!all:~2!"
set ^"all=!all:#L=^

!"
set "all=!all:#S=#!"
)
echo !all!

代码的作用是什么?
首先,findstr /n ^^ 会在每一行前面加上一个行号和一个冒号,比如

1:My first Line
2:; beginning with a semicolon
3:
4:there was an empty line

这解决了空行的问题,并且标准的EOL字符;可以被忽略。
要获取该行的内容,在禁用延迟扩展时将值设置为变量,这解决了!^ 字符的问题。

去掉行号和冒号,会启用延迟扩展(不行,:的delim解决不了)。

然后将所有#替换为#S,这将首先完成,因为删除该行的前缀可能为空,替换将失败。
但是我为什么要替换它呢?
那是因为我无法在此处插入换行符,因为以下 FOR/F 会因嵌入换行符而失败,
所以我只添加换行标记(在这种情况下我使用#L),但文件的内容也可以包含#L,但通过将所有#替换为#S all标记是独一无二的。

在标记之后,使用endlocal 关闭/禁用延迟扩展存在问题,但保留修改后的allline 变量的内容。
这是通过FOR/F-endlocal 技巧完成的,因为%%p 可以在endlocal 屏障后面传输内容。

然后在阅读完整的文件后,我检查all 是否已定义,因为它对于空文件来说是空的。
然后第一个 换行标记 #L 将被删除,所有其他标记都将替换为真正的换行符。
然后更安全的#S 将恢复为#

就是这样,所以即使是这个解决方案也很明显......

【讨论】:

  • +1,我开始走 FOR /F 路线,但后来我想,“我为什么要做所有这些工作?” :-)
  • 非常有趣 :) 但后来我作为一个卑微的蚱蜢来到这里,只想学习 DOS 的内部结构......我很谦卑你会给它旧大学的尝试......但非常感谢为您在国内外所做的所有工作!我会一直走下去
  • 这当然很棒!因为我的源文件(aux)实际上是一个需要插入到 sql 记录中的 html 文件(并且源包含 ! 在第一行)。所以+2对于那段有见地的代码!所以现在我只需要检查文件的大小以确保它低于 8k 限制,如果没有,那么我可以拆分!全部!进入!all1! !all2! 等等。我的文件大约有一半是 8k-30K,所以最大可能是四五个!all!瓦尔的。感谢分享
猜你喜欢
  • 2011-09-11
  • 2019-09-24
  • 2021-12-27
  • 1970-01-01
  • 2012-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多