如何使用批处理脚本将子串从反转到某个字符

时间:2018-05-18 04:08:06

标签: windows batch-file cmd

我将这些字符串作为文件名列表

abc-cdef-ijklm-2018.04.02-vendor1.1.0.0
abc-cdef-pqrs-2018.03.22-writer1.2.0.0
abc-cdef-lmno-2017.03.22-reader22.5.0.5

我需要从最后5个字母之后的反向的每一行中提取这些子字符串,直到短划线-

vendor1
writer1
reader22

如何使用简单的批处理脚本执行此操作。

4 个答案:

答案 0 :(得分:1)

有几种不同的方法可以解决这个问题。这是一个非常简单的问题:

@echo off
setlocal

rem Process the strings (from test.txt file)
for /F "delims=" %%a in (test.txt) do call :extract "%%a"
goto :EOF


:extract

REM ECHO ON

set "string=%~1"

rem Extract *the last part* after the last dash
set "string=%string:-=" & set "string=%"

rem Extract *the first part* before the first dot
set "string=%string:.=" & rem "%"

@REM ECHO OFF

echo %string%
exit /B

例如,如果这是输入文件 test.txt

abc-cdef-ijklm-2018.04.02-vendor1.1.0.0
abc-cdef-pqrs-2018.03.22-writer1.2.0.0
abc-cdef-lmno-2017.03.22-reader22.5.0.5

这是输出:

vendor1
writer1
reader22

此方法使用简单子字符串替换来执行所需部分的提取。 审核方法而不是 explain 更简单,因此您可以激活ECHO ON@ECHO OFF命令并自行检查方法有效。

如果您需要进一步说明,请参阅this topic

答案 1 :(得分:0)

如果由-分隔的子串数为常数5,则可以在批处理文件中使用以下代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "_FileName1=abc-cdef-ijklm-2018.04.02-vendor1.1.0.0"
set "_FileName2=abc-cdef-pqrs-2018.03.22-writer1.2.0.0"
set "_FileName3=abc-cdef-lmno-2017.03.22-reader22.5.0.5"

for /F "tokens=1* delims==" %%A in ('set _FileName') do (
    for /F "eol=| tokens=5 delims=-" %%C in ("%%B") do (
        for /F "eol=| delims=." %%D in ("%%C") do (
            echo Last part of "%%B" is: %%D
        )
    )
)
endlocal
pause

请忽略此处使用的最外部 FOR 循环,仅处理名称以_FileName开头的未确定数量的环境变量的值。

第二个 FOR 循环处理一个文件名作为循环变量B,在这种情况下,通过使用-作为指定的分隔符将其拆分为子字符串(标记)与delims=-

感兴趣的只是第五个子串。因此tokens=5指定只应将第五个子字符串分配给指定的循环变量A

此外,行尾字符会从默认;修改为|,以避免 FOR 完全忽略以分号开头的文件名。文件名名称中不能有垂直条。

所以第二个 FOR 循环将循环变量C分配给字符串:

vendor1.1.0.0
writer1.2.0.0
reader22.5.0.5

第三个 FOR 循环用于删除第一个点后的所有内容 使用.作为分隔符将此字符串拆分为子字符串,并将第一个子字符串分配给指定的循环变量D,默认情况下未明确指定tokens=选项。再次eol=|用于避免 FOR 完全忽略该字符串,如果此字符串以分号开头。

因此,循环变量D在此示例中保留了进一步处理所需的字符串,例如将其打印到控制台。

这是另一个解决方案,它只是在一个子程序LastPart中使用字符串替换,这个子程序在批处理文件的中间异常嵌入,速度较慢,但​​也适用于具有可变数量的连字符分隔子串的文件名。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "_FileName1=abc-cdef-ijklm-2018.04.02-vendor1.1.0.0"
set "_FileName2=abc-pqrs-2018.03.22-writer1.2.0.0"
set "_FileName3=lmno-2017.03.22-reader22.5.0.5"
goto ProcessFileNames


:LastPart
set "FileName=%~1"
rem Get file name without the last six characters.
set "FileName=%FileName:~0,-6%"

rem Remove from file name in a loop everything from beginning to first hyphen
rem character with removing also the hyphen until this is not possible anymore
rem because of file name string not containing anymore a hyphen.

:LastHyphen
set "LastPart=%FileName:*-=%"
if not "%LastPart%" == "%FileName%" set "FileName=%LastPart%" & goto LastHyphen

echo Last part of %1 is: %LastPart%

rem Exit subroutine LastPart and return to calling FOR command line.
goto :EOF


:ProcessFileNames
for /F "tokens=1* delims==" %%A in ('set _FileName') do call :LastPart "%%B"
endlocal

最后是上面的另一个变体,每个文件名末尾的字符数也可以变化。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "_FileName1=abc-cdef-ijklm-2018.04.02-vendor1.1.0.0"
set "_FileName2=abc-pqrs-2018.03.22-writer1.2.0.50"
set "_FileName3=lmno-2017.03.22-reader22.5.10.15"
goto ProcessFileNames


:LastPart
set "FileName=%~1"

rem Remove from file name in a loop everything from beginning to first hyphen
rem character with removing also the hyphen until this is not possible anymore
rem because of file name string not containing anymore a hyphen.

:LastHyphen
set "LastPart=%FileName:*-=%"
if not "%LastPart%" == "%FileName%" set "FileName=%LastPart%" & goto LastHyphen

rem Get string up to first dot from last part of file name.
for /F "eol=| delims=." %%I in ("%LastPart%") do set "LastPart=%%I"

echo Last part of %1 is: %LastPart%

rem Exit subroutine LastPart and return to calling FOR command line.
goto :EOF


:ProcessFileNames
for /F "tokens=1* delims==" %%A in ('set _FileName') do call :LastPart "%%B"
endlocal

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

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?

答案 2 :(得分:0)

目前还不清楚你打算如何获取文件列表,所以我将展示一些方法。此外,这假设您的文件格式完全作为示例。

假设您的文件有.PEM扩展名,我们可以这样做:

@echo off
for /f "tokens=1-10 delims=-." %%a in ('dir /b *.PEM') do echo %%g

如果文件中有文件名列表,我们称之为内容如下的file.txt

abc-cdef-ijklm-2018.04.02-vendor1.1.0.0
abc-cdef-pqrs-2018.03.22-writer1.2.0.0
abc-cdef-lmno-2017.03.22-reader22.5.0.5

然后这个应该做:

@echo off
for /f "tokens=1-10 delims=-." %%a in ('type file.txt') do echo %%g

但是,如果你明确表示如何访问文件名,那么我可以修改我的答案。

答案 3 :(得分:0)

要提取最后- - 分隔的项目,您可以使用标准for循环,如下面的方法。诀窍是用标准分隔符替换每个-,如 SPACE ,并将每个部分括在""之间,以保护所有其他出现的分隔符。所以这是相关的代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_FILE=%~1" & rem // (use first command line argument)

rem // Read file line by line (empty lines are ignored):
for /F usebackq^ delims^=^ eol^= %%L in ("%_FILE%") do (
    rem // Store line string:
    set "LINE=%%L"
    setlocal EnableDelayedExpansion
    rem /* Enclose line string within `""` and replace every `-` by `" "`,
    rem    which results in several space-delimited items within `""`: */
    for %%I in ("!LINE:-=" "!") do (
        endlocal
        rem // Store (overwrite) current item with surrounding `""` removed:
        set "ITEM=%%~I"
        setlocal EnableDelayedExpansion
    )
    rem // Splif off first `.` and everything after from last item:
    for /F "tokens=1 delims=. eol=." %%V in ("!ITEM!") do (
        endlocal
        rem // Return extracted string portion:
        echo(%%V
        setlocal EnableDelayedExpansion
    )
    endlocal
)

endlocal
exit /B

如果文本文件包含字符*?<>",则此脚本将失败。

鉴于该脚本名为data-extract.bat,要处理的字符串存储在名为data.txt的文本文件中,并且两者都放在当前的directlry中,运行如下脚本:

data-extract.bat "data.txt"

要将输出存储在另一个文件中(与data.txt不同!),请使用:

data-extract.bat "data.txt" > "data_NEW.txt"