用于更新 Tilda 分隔文件中的值的批处理脚本

问题描述 投票:0回答:2

这里是输入文件:

!~ItemID~RevID~DsetType~DsetName~DsetDesc~FileRef~File~RelationName
DR_QPC_M999~A~PDFA~DR_QPC_M999_A_001~~PDF~.\APR28_Batch1\DR_QPC_M999\A\DR_QPC_M999_A_001.pdf~IMAN_specification
DR_QPC_M999~A~PDFA~DR_QPC_M999_A_001~Imported QPC~PDF~.\APR28_Batch1\DR_QPC_M999\A\DR_QPC_M999_A_001.pdf~IMAN_specification

我在下面写了这个脚本来检查第三个值并根据该值更新第六个值。

所以,映射是这样工作的

如果第三个值是 PDFA --> 将第三个值 PDFA 更新为 R8PDFA
然后检查第 6 个值是否为 PDF 然后 --> 将第 6 个值更新为 R8PDFA.

我得到的输出:

!~ItemID~RevID~DsetType~DsetName~DsetDesc~FileRef~File~RelationName 
DR_QPC_M999~A~R8PDFA~DR_QPC_M999_A_001~PDF~.\APR28_Batch1\DR_QPC_M999\A\DR_QPC_M999_A_001.pdf~IMAN_specification~ 
DR_QPC_M999~A~R8PDFA~DR_QPC_M999_A_001~Imported QPC~R8PDFA~.\APR28_Batch1\DR_QPC_M999\A\DR_QPC_M999_A_001.pdf~IMAN_specification 

问题出在第二行: 如果输入值是这样的:

DR_QPC_M999~A~PDFA~DR_QPC_M999_A_001~~PDF~.\APR28_Batch1\DR_QPC_M999\A\DR_QPC_M999_A_001.pdf~IMAN_specification

也就是说,如果它有两个 Back to back

~~
这样它就不会把它当作两个单独的分隔符。但是如果我像
~ ~
一样输入输入文件,脚本就可以工作了。

需要一个批处理脚本来解决这个问题。

batch-file
2个回答
0
投票
@ECHO OFF
SETLOCAL
rem The following settings for the directories and filenames are names
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "filename1=%sourcedir%\q76161584.txt"
SET "outfile=%destdir%\outfile.txt"

(
FOR /f "usebackqdelims=" %%e IN ("%filename1%") DO (
 SET "line=%%e"
 CALL :process
)
)>"%outfile%"

GOTO :EOF

:process
:: remove variables starting #
FOR /F "delims==" %%y In ('set # 2^>Nul') DO SET "%%y="
SET "#line=%line%"
SET /a #index=-1
:nextfield
SET /a #field+=1
SET /a #fieldlength=-1

:nextchar
SET /a #index+=1
SET /a #fieldlength+=1
SET "#char=%line:~0,1%"
SET "line=%line:~1%"
IF "%#char%" neq "~" GOTO nextchar
IF %#field%==3 (
 SET /a #field3end=#index
 SET /a #field3start=#index-#fieldlength
 SET /a #field3length=#fieldlength
)
IF %#field%==6 (
 SET /a #field6end=#index
 SET /a #field6start=#index-#fieldlength
 SET /a #field6length=#fieldlength
 GOTO subs
)
GOTO nextfield

:subs
IF %#field3length% neq 4 GOTO nosubs
CALL SET "test=%%#line:~%#field3start%,4%%"
IF "%test%" neq "PDFA" GOTO nosubs
IF %#field6length% neq 3 GOTO sub3
CALL SET "test=%%#line:~%#field6start%,3%%"
IF "%test%" equ "PDF" CALL SET "#line=%%#line:~0,%#field6start%%%R8PDFA%%#line:~%#field6end%%%"
:sub3
CALL SET "#line=%%#line:~0,%#field3start%%%R8PDFA%%#line:~%#field3end%%%"

:nosubs
ECHO %#line%

GOTO :eof

OK - 回到基础。由于可用的测试数据有限,这个过程对我有用。

将每行数据依次赋值给

%%e
line

通过逐个字符处理

line
来计算每个字段的开始和长度。

记录字段 3 和 6 的开始和长度。

在找到字段 6 时应用替换规则。

不清楚是否只有在字段3发生替换时才进行字段6的替换。我假设它是。

然后必须以相反的顺序执行替换,因为每个替换都会影响后面字段的起始位置。


0
投票

您的问题中有很多未指定的细节。例如:

  • 第一个字段可以为空吗?
  • 最后一个字段可以为空吗?
  • 相邻两个以上的字段可以为空吗?
  • 第4个字段(目标字段3之后的那个)可以为空吗?
  • 第7个字段(目标字段6之后的那个)可以为空吗?

下面的代码假设前面所有问题的答案都是:否。

@echo off
setlocal DisableDelayedExpansion

set "header="
(for /F "delims=" %%a in (input.txt) do (
   if not defined header (
      set "header=1"
      echo %%a
   ) else (
      call :processLine "%%~a" < NUL
   )
)) > output.txt
goto :EOF


:processLine
setlocal EnableDelayedExpansion
set "line=%~1"
set "i=0"
set "changed3="
:nextField
   set /A i+=1
   set "rest=%line:*~=%"
   if "%rest%" equ "%line%" goto endFields
      if "%rest:~0,1%" neq "~" (
         set "field=!line:%rest%=!"

         if %i% equ 3 if "!field!" equ "PDFA~" (
            set "field=R8PDFA~"
            set "changed3=1"
         )
         if %i% equ 6 if "!field!" equ "PDF~" if defined changed3 (
            set "field=R8PDFA~
         )

         set /P "=!field!"
      ) else (
         set "field=!line:%rest:~1%=!"
         set /P "=!field!"
         set /A i+=1
         set "rest=%rest:~1%"
      )
   set "line=%rest%"
goto nextField
:endFields
echo %line%
exit /B

该方法包括从行的开头消除直到第一个

~
字符并获得余数。然后,从该行中删除此余数以获得第一个以 Tilda 分隔的字段。重复此过程,直到处理完所有字段。

如果上述问题之一的答案是肯定的,则应修改代码。其中一些要点可以通过非常简单的方式实现,有些则不能……

© www.soinside.com 2019 - 2024. All rights reserved.