简体   繁体   English

为什么Windows批处理文件输出的行数组中缺少特殊字符?

[英]Why are special characters missing in array of lines output by Windows batch file?

I want to insert data (only rows having extended keyword) present in .txt file into Oracle database in the format ID,Data,Date,Project Name where ID, date and project name are present in environment variables. 我想将.txt文件中存在的数据(仅具有扩展关键字的行)以ID,Data,Date,Project Name的格式插入到Oracle数据库中其中ID,日期和项目名称存在于环境变量中。

File.txt has below data: File.txt具有以下数据:

Writing main object(name=abc)
writing Extended object (name=%abc(123&rest,type=pqr)

logdata.txt should have below data: logdata.txt应该包含以下数据:

A1234C,(name=%abc(123&rest,type=pqr),12022018_11:12:20,DEV:Sales Project

While copying the data, special characters like %,( etc present in the file.txt are missing in the output file logdata.txt . 复制数据时,输出文件logdata.txt中缺少file.txt中的%,(等特殊字符。

Please find below code : 请找到以下代码:

set file=D:\MSTR_CICD\file.txt
for /F "usebackq tokens=2*delims=(" %%a in (`findstr  "extended" "%file%"`) do (
    set /A i+=1
    call set array[%%i%%]=%%a
    call set n=%%i%%
)

for /L %%i in (1,1,%n%) do call echo %User_ID%,%%array[%%i]%%,%Timestamp%,%proj%  >> D:\MSTR_CICD\Batch_Script\logdata.txt

Please correct the code or let me know how can i achieve this. 请更正代码或让我知道我该如何实现。 Also, my input file can have any special character as it contain logs of an application. 另外,我的输入文件可以包含任何应用程序日志,因此可以具有任何特殊字符。

This batch file can be used for this task: 此批处理文件可用于此任务:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "proj=DEV:Sales Project"
set "User_ID=A1234C"
set "Timestamp=12022018_11:12:20"
set "InputFile=D:\MSTR_CICD\file.txt"
set "DataFile=D:\MSTR_CICD\Batch_Script\logdata.txt"

if exist "%InputFile%" (
    for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /I /C:Extended "%InputFile%"') do (
        set "DataLine=%%I"
        setlocal EnableDelayedExpansion
        set "DataLine=!DataLine:*(=(!"
        set "DataLine=!DataLine:"=""!"
        echo %User_ID%,"!DataLine!",%Timestamp%,%proj%
        endlocal
    )
) >"%DataFile%"

if exist "%DataFile%" for %%I in ("%DataFile%") do if %%~zI == 0 del "%DataFile%"

:EndBatch
endlocal

FINDSTR runs in the separate command process started by FOR in background with cmd.exe /C a case-insensitive, literal search for the string Extended on the input file and outputs all lines containing this string to handle STDOUT . FINDSTR在由cmd.exe /C在后台由FOR启动的单独命令进程中运行,该命令不区分大小写地在输入文件中搜索字符串Extended ,并输出包含该字符串的所有行以处理STDOUT

FOR captures this output and processes them line by line. FOR捕获此输出并逐行处理它们。 FOR ignores empty lines and by default also lines starting with a semicolon because of ; FOR忽略空行,默认情况下也开始因为一个分号线; is the default end of line character. 是默认的行尾字符。 And FOR splits up the line into substrings (tokens) using space/tab as delimiter and assigns just the first substring to specified loop variable by default. 并且, FOR使用空格/制表符作为分隔符将行分成子字符串(令牌),并且默认情况下仅将第一个子字符串分配给指定的循环变量。

By using the FOR option string delims^=^ eol^= an empty list of delimiters and and no end of line character is set to disable line splitting and ignoring lines starting with a semicolon. 通过使用FOR选项字符串delims^=^ eol^=一个空的定界符列表,并且不设置行尾字符来禁用行拆分,并忽略以分号开头的行。 As this special option string cannot be enclosed in double quotes, it is necessary to escape the space and the two equal signs with caret character to get those three characters outside a double quoted argument string interpreted as literal characters and not as argument string separators. 由于此特殊选项字符串不能用双引号引起来,因此必须转义空格和带有尖号字符的两个等号,以使这三个字符在双引号参数字符串之外解释为文字字符而不是参数字符串分隔符。

The entire line as output by FINDSTR found in file is assigned to environment variable DataLine . 在文件中找到的FINDSTR输出的整个行都分配给环境变量DataLine This is done with delayed environment variable expansion disabled to process also lines correct containing one or more exclamation marks. 这是通过禁用延迟的环境变量扩展来完成的,也可以处理包含一个或多个感叹号的正确行。 Otherwise cmd.exe would double parse the line set "DataLine=%%I" after having replaced %%I by the current line and would interpret every ! 否则,在用当前行替换%%I之后, cmd.exe将对行set "DataLine=%%I"进行双重分析,并解释每一个! in the line as begin/end of an environment variable reference resulting in unwanted modification of the line before assigning it to the environment variable. 在该行中作为环境变量引用的开始/结束,导致在将该行分配给该环境变量之前导致对该行进行不必要的修改。

The usage of command CALL on a line with command SET results also in double parsing the command line before executing the command SET which is the reason why some characters are missing in the environment variables array produced by your code. 在命令SET的行上使用命令CALL还会导致在执行命令SET之前对命令行进行双重解析,这就是代码生成的环境变量数组中缺少某些字符的原因。

For details see also How does the Windows Command Interpreter (CMD.EXE) parse scripts? 有关详细信息,另请参阅Windows命令解释器(CMD.EXE)如何解析脚本?

After having assigned the line to the environment variable, it is necessary to enable delayed expansion to further process the data line in the FOR loop. 在将行分配给环境变量之后,有必要启用延迟扩展以进一步处理FOR循环中的数据线。 That makes the batch file slow, but can't be avoided in this case. 这会使批处理文件变慢,但在这种情况下无法避免。 Read this answer for details about the commands SETLOCAL and ENDLOCAL . 阅读此答案以获取有关命令SETLOCALENDLOCAL的详细信息。

The first modification on the data line is removing everything left to first ( . 数据行的第一个修改是删除保留到first (

The second modification on the data line is replacing all " by "" in the line to escape every double quote according to CSV specification. 数据行的第二个修改是将行中的所有"替换为""替换为根据CSV规范转义的每个双引号。

Then the remaining data line is output together with the other data enclosed in double quotes as the data line can contain also one or more commas which requires according to CSV specification that the data is enclosed in double quotes. 然后,将剩余的数据行与其他用双引号引起来的数据一起输出,因为该数据行还可以包含一个或多个逗号,根据CSV规范,该数据要求将数据用双引号引起来。

For CSV specification read for example the Wikipedia article about comma-separated values . 对于CSV规范,请阅读Wikipedia中有关逗号分隔值的文章。

Everything output by ECHO inside FOR loop is redirected to the specified data file which overwrites a by chance already existing data file with same name. ECHOFOR循环中输出的所有内容都将重定向到指定的数据文件,该文件将偶然覆盖一个已经存在且具有相同名称的数据文件。

It is possible that FINDSTR does not find any line containing Extended in any case resulting in producing a data file with 0 bytes. 在任何情况下, FINDSTR都可能找不到包含Extended任何行,从而导致产生一个0字节的数据文件。 The empty data file is deleted by the second FOR . 空数据文件被第二个FOR删除。

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully. 为了了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • del /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM