【问题标题】:Passing a Multi-Line String to Batch File将多行字符串传递给批处理文件
【发布时间】:2015-02-06 15:20:56
【问题描述】:

我正在将一个多行字符串从一个 vbscript 传递给一个批处理文件。但是,当我尝试从批处理文件中获取整个字符串时,它只接收第一行。如何让批处理文件知道读取整个字符串,而不是在换行符处停止。

输入:
C:\组件A

C:\组件B

C:\组件C

VBScript:

multstring = "C:\Component_A" + Chr(13) + Chr(10) + "C:\ComponentB" +
       Chr(13) + Chr(10) + "C:\ComponentC" + Chr(13) + Chr(10)

script_path = "runscript.bat """ + multstring + """

Shell(script_path)

批次:

set "scriptargs=%~1"
echo "%scriptargs%"
setlocal enableDelayedExpansion
echo !scriptargs!

我得到的输出:

C:\组件A

想要的输出:

C:\组件A

C:\组件B

C:\组件C

【问题讨论】:

  • cmd 不适用于多行字符串。 一次只能一行。您可以将| 输入到要处理的脚本中,但这需要一些花哨的脚本逻辑。我建议将您的输入与分隔符(如 ; )连接成一行,然后在脚本中使用 for 解析它。
  • @DavidRuhmann 这正是我最终所做的。通过特殊的分隔符分隔。感谢您的回复。
  • 您发布的 VBS 代码无效 - 它无法提供您声称的输出。总结代码时请注意发布工作示例。
  • @DavidRuhmann - cmd 可以处理环境变量中的多行字符串。但确实不能将多行值作为命令行参数传递。

标签: shell batch-file vbscript


【解决方案1】:

多行字符串不能通过命令行参数传递给批处理文件,但新行可以包含在环境变量中。

VBS可以定义一个带有换行符的环境变量,然后你调用的批处理脚本可以通过延迟扩展读取并显示该值。

test.vbs

set wshShell = CreateObject("WScript.Shell")
set Env=wshShell.Environment("PROCESS")

multstring="C:\Component_A" + Chr(13) + Chr(10) + "C:\ComponentB" + _
            Chr(13) + Chr(10) + "C:\ComponentC" + Chr(13) + Chr(10)

Env("arg1") = multstring

script_path = "runscript.bat arg1"

wshShell.Run script_path

runscript.bat

@echo off
setlocal enableDelayedExpansion
echo !%1!
pause

请注意,这适用于由 VBS 调用的批处理脚本,因为新的批处理脚本继承了 VBS 环境的副本。

如果批处理脚本调用 VBS,则 VBS 无法通过环境变量将值传递回调用方,因为一旦 VBS 结束,VBS 环境就会丢失。

【讨论】:

  • 吹毛求疵:您可以将多行字符串传递给批处理文件,但访问它们有点棘手
【解决方案2】:

正如 dbenham 提到的,通过引用传递多行字符串是个好主意。

但如果你真的需要按值传递它们这也是可能的
问题是要访问它们。

这是How to receive even the strangest command line parameters? 的改编变体。

@echo off
setlocal DisableExtensions DisableDelayedExpansion
REM Write the complete parameter to a temp file
@echo on
@(for %%A in (%%A) do (
    @goto :break
    REM # %1 #
    REM
)) > param.tmp
:break
@echo off

REM receive all lines from the temp file and store them in an array
setlocal EnableExtensions
set cnt=0
for /F "skip=3 delims=" %%a in (param.tmp) DO (
    set /a cnt+=1
    setlocal EnableDelayedExpansion
    for /F %%n in ( "!cnt!" ) do (
        setlocal DisableDelayedExpansion
        set "param%%n=%%a"
    )
)
setlocal EnableDelayedExpansion
set \n=^


REM Build the \n variable with a linefeed character, the two empty lines are required

REM Build from the array a single parameter
set /a cnt-=2
set "param1=!param1:~6!"    REM Remove the 'REM #' from the first line
set "param%cnt%=!param%cnt%:~0,-3!" REM Remove the trailing '#' from the last line
set "param="
for /L %%n in (1 1 !cnt!) do (
    if %%n GTR 1 set "param=!param!!\n!"
    set "param=!param!!param%%n:~1!"
)
echo The param is: '!param!'

来自控制台的示例调用(需要空行!):

test.bat ^"hello^

Line2^

Line3"

无法访问回车,因为它们总是被 cmd.exe 删除

但是当使用次优内容时仍然存在问题。

【讨论】:

  • 1) 您的 SET "var=content" REM ... 备注内容中有引号会导致代码失效。 2)您正在为结果添加尾随空格。 3) 我看不出你如何区分 \n 和 \r\n。 4)您在某些行上有尾随空格问题 5)您没有显示如何调用您的脚本 - 我相信它需要引用变量 "!argVar!" 的延迟扩展,这意味着您仍然会通过引用传递值VBS 的,并且必须通过 CMD /V:ON /C ... 运行批处理
  • 1) 我不知道你指的是哪几行? 2)不,没有尾随空格,由样本证明 3)您根本无法检测到带有批次的\r 4)哪些行? 5)我添加了一个样本,通过by value
  • 1) 知道了(并修复了它),我用其他代码进行了测试,而不是发布的代码:-)
  • 当我用 4 行测试一个参数时,第一行附加了 2 个尾随空格,第二行和第三行添加了 1 个尾随空格,最后一行是可以的。我通过在末尾添加echo(!param!>test.txt 进行测试,并使用十六进制编辑器查看内容。
  • 我现在看到 param.tmp 已剥离所有 \r,然后每一行都以 \r\n 终止。所以是的,用这种技术检测\r 是不可能的。
猜你喜欢
  • 1970-01-01
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-23
  • 1970-01-01
  • 2010-09-06
相关资源
最近更新 更多