首页 > 解决方案 > 替换输出中的字符串

问题描述

我有文件 C:/test.txt,其内容如下。

05/13/2017 07:29:34 Value=           \\america.com\efpf_share\efpf\ipm_files
05/13/2017 07:29:41 Value=           \\america.com\efpf_share\efpf\ipm_files
05/17/2017 08:31:54 Value=           \\america.com\efpf_share\efpf\ipm_files
05/17/2017 08:32:03 Value=           \\america.com\efpf_share\efpf\ipm_files

我想提取 'epfp' 或任何字符串出现在这个地方并将其转换为大写,如果它附加了测试(作为 epfptest),那么它应该拆分EPFP-TEST。为了提取我正在运行以下代码并将输出重定向到temp1.txt文件中

findstr "Value=" C:\test.txt| findstr america > "C:\temp.txt" && for /l %l in (1,1,1) do @for /f "tokens=3* delims=." %a in ('findstr /n /r "^" "C:\temp.txt" ^| findstr /r "^%l:"') do @echo %b > c:\temp1.txt

现在 temp1.txt 文件的内容如下:

com\efpf_share\efpf\ipm_files

现在最后我从下面的代码中提取 efpf 它给了我如下输出:

for /f "tokens=3 delims=\" %a in (c:\temp1.txt) do @echo %a
epfp

我希望此输出或转换为EPFP(在 uppercare 中),如果此输出没有附加测试字符串,那么它应该只拆分为 EPFP-TEST

注意:最终输出可以是任何东西(在本例中为 epfp),如果此输出包含附加的“测试”字符串,我也希望此转换为大写,则应将其拆分为“ STRING -TEST

标签: batch-file

解决方案


这个测试文件修改任务绝对不应该使用批处理文件和纯 Windows 命令处理器命令来完成。这个任务有更好的脚本语言。

使用功能强大的文本编辑器(如 UltraEdit)或任何其他支持 Perl 正则表达式的文本编辑器来修改文件内容也会更有用。如果还没有连字符并且整个文件夹名称不是 ,则搜索(\\[^\\]+\\)(?=ipm_files)并使用 as replace 字符串\U$1\E会将目录名称更改ipm_files为大写,搜索(?<!\\|-)TEST(?=\\ipm_files)并使用 as replace 字符串-TEST将插入连字符。TESTTEST

但是,这是此任务的注释批处理文件解决方案:

@echo off
if not exist "%~dp0Test.txt" goto :EOF
setlocal EnableExtensions DisableDelayedExpansion

set "Modified=0"
set "DataFile=%~dp0Test.txt"
set "TempFile=%TEMP%\%~n0.tmp"
del "%TempFile%" 2>nul

for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "%DataFile%" 2^>nul') do (
    set "Line=%%I"
    call :ProcessLine
)

if %Modified% == 1 move /Y "%TempFile%" "%DataFile%"
del "%TempFile%" 2>nul

endlocal
goto :EOF

rem The subroutine ProcessLine removes first line number and colon inserted
rem by FINDSTR at beginning of each line to process correct also empty lines
rem in data file. The subroutine jumps to output of line in case of current
rem line is an empty line.

rem Next the line is split up into substrings using backslash as delimiter.
rem Of interest are only the fourth and fifth substrings. The fifth substring
rem should be ipm_files to identify the current line as a line to process.
rem A jump to writing the line into temporary file is done if this condition
rem is not true. Otherwise the fourth substring is assigned to a variable
rem because that string is the folder name to modify by this batch file.

rem Each ASCII character in the folder name is replaced by its upper case character.

rem If the entire new folder name is TEST, just do the replace and don't change
rem the folder name to -TEST. If the new folder name ends already with -TEST,
rem just do the replace. But if new folder name ends with only TEST, replace
rem just TEST by -TEST with hyphen.

rem A case-sensitive comparison of current and new folder name is done before
rem running the folder replace on line to determine if the replace is really
rem necessary at all. The modification information is saved in an environment
rem variable which is passed over local environment of subroutine to main code
rem above. This information is used finally to determine if the data file must
rem be replaced at all by the temporary file because of a modification is made
rem or the temporary file can be simply deleted as being equal with data file.

:ProcessLine
setlocal EnableDelayedExpansion
set "Line=!Line:*:=!"
if not defined Line goto WriteLine

for /F "tokens=4,5 delims=\" %%A in ("!Line!") do (
    if /I not "%%B" == "ipm_files" goto WriteLine
    set "CurFolderName=%%A"
)

set "NewFolderName=%CurFolderName%"
for %%C in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do set "NewFolderName=!NewFolderName:%%C=%%C!"

if "%NewFolderName%" == "TEST" goto DoReplace
if "%NewFolderName:~-5%" == "-TEST" goto DoReplace
if "%NewFolderName:~-4%" == "TEST" set "NewFolderName=%NewFolderName:~0,-4%-TEST"

:DoReplace
if "%CurFolderName%" == "%NewFolderName%" goto WriteLine
set "Modified=1"
set "Line=!Line:%CurFolderName%\ipm_files=%NewFolderName%\ipm_files!"

:WriteLine
echo(!Line!>>"%TempFile%"
endlocal & set "Modified=%Modified%"
goto :EOF

%~dp0Test.txt必须用相对或绝对路径的数据文件的真实文件名替换两次。

在我的回答中描述了顶部主代码中第一个FOR循环的目的:
如何逐行读取和打印文本文件的内容?

其他命令行由主代码和子程序之间的注释来解释。

要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • call /?
  • del /?
  • echo /?
  • endlocal /?
  • findstr /?
  • goto /?
  • if /?
  • move /?
  • rem /?
  • setlocal /?

推荐阅读