简体   繁体   中英

Windows Batch file count numbers of tokens

I have this batch file:

@ECHO OFF
SETLOCAL EnableDelayedExpansion

IF EXIST OPERATORS_FULL.csv DEL OPERATORS_FULL.csv
IF EXIST OPERATORS_FULL.tmp DEL OPERATORS_FULL.tmp

FOR %%A IN ( OPERATORS_*.csv ) DO (
    :: get attribute from filename
    SET "attr=%%A"
    SET "attr=!attr:OPERATORS_=!"
    SET "attr=!attr:.csv=!"
    :: split string to get date suffix
    FOR /F "tokens=1,2 delims=_" %%G IN ( "!attr!" ) DO (
        SET attr=%%G
        SET date_=%%H
    )
    :: dump CSVs, skipping each header line, adding the attributes from the filename
    FOR /F "skip=1 tokens=*" %%G IN ( %%A ) DO ECHO %%G;!attr!;!date_! >> OPERATORS_FULL.tmp
)

REN OPERATORS_FULL.tmp OPERATORS_FULL.csv

The attr value is variable and it can contain 1,2,3,4,... of "_" character. So the tokens=1,2 is not functionally everytime. I want the last token of the "attr" variable.

Any suggestions?

UPDATE

I tried this:

@ECHO OFF
SETLOCAL EnableDelayedExpansion

IF EXIST Operatori_FULL.csv DEL Operatori_FULL.csv
IF EXIST Operatori_FULL.tmp DEL Operatori_FULL.tmp

FOR %%A IN ( Operatori_*.csv ) DO (
    :: get attribute from filename
    SET "attr=%%A"
    SET "attr=!attr:Operatori_=!"
    SET "attr=!attr:.csv=!"
        set "date_=!attr!"
:loop
        if "!date_:_=!" == "!date_!" goto :gotdate
        for /f "delims=_ tokens=1,*" %%g in ("!date_!") do echo %%h

pause
        goto :loop
:gotdate
        :: dump CSVs, skipping each header line, adding the attributes from the filename
    FOR /F "skip=1 tokens=*" %%G IN ( %%A ) DO ECHO %%G;!attr!;!date_! >> Operatori_FULL.tmp
)

REN Operatori_FULL.tmp Operatori_FULL.csv

But the snippet remove only the first part of string (A2A_)

This code extracts the last token from attr variable and store it in date_ variable:

    rem split string to get date suffix
    set "newAttr="
    set "date_="
    FOR %%G IN ( "!attr:_=" "!" ) DO (
        SET "newAttr=!newAttr!_!date_!"
        SET "date_=%%~G"
    )
    SET "attr=!newAttr:~2!"

If you just need the last token, the code is simpler:

FOR %%G IN ( "!attr:_=" "!" ) DO SET "date_=%%~G"

Hopefully this will be close to what you want (not sure whether attr will be what you need):

@ECHO OFF
SETLOCAL EnableDelayedExpansion

IF EXIST Operatori_FULL.csv DEL Operatori_FULL.csv
IF EXIST Operatori_FULL.tmp DEL Operatori_FULL.tmp

FOR %%A IN ( Operatori_*.csv ) DO (
    :: get attribute from filename
    SET "attr=%%A"
    SET "attr=!attr:Operatori_=!"
    SET "attr=!attr:.csv=!"
    set "date_=!attr!"
    call :getLast
    :: dump CSVs, skipping each header line, adding the attributes from the filename
    FOR /F "skip=1 tokens=*" %%G IN ( %%A ) DO ECHO %%G;!attr!;!date_! >> Operatori_FULL.tmp
)

REN Operatori_FULL.tmp Operatori_FULL.csv
goto :eof

:getLast
    if "!date_:_=!" == "!date_!" goto :eof
    for /f "delims=_ tokens=1,*" %%g in ("!date_!") do set "date_=%h"
    goto :getLast

The subroutine getLast will strip date_ to its last component (delimited by underscores). Its operation is: while there's an underscore in date_ it splits it into "the first token" and "all the rest" and sets date_ to "all the rest". When there are no (more) underscores, date_ is left with the last underscore-delimited component of its original value.

The "underscore stripping code" needs to be a "subroutine" since you cannot (to the best of my knowledge) use labels inside the outer for loop.

Here is a possible solution, that replaces every _ by a line-break temporarily:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "STRING=%~1" & rem // (first argument is taken as input string)
set "CHAR=_"     & rem // (this is the character of interest)
rem // Build line-break:
(set ^"LF=^
%= empty line =%
^")

rem /* Replace each predefined character by a line-break,
rem    and enclose every line string portion within `""`;
rem    these quotation marks are needed to handle empty strings: */
setlocal EnableDelayedExpansion
if defined STRING set ^"STRING=^"!STRING:%CHAR%=^"^%LF%%LF%^"!^"^"
rem /* Loop through all the lines in the modified string and
rem    assign each line string portion to a variable with
rem    the surrounding `""` removed; when the loop is finished,
rem    the last line is stored in the variable: */
for /F delims^=^ eol^= %%S in ("!STRING!") do (
    endlocal
    set "LAST=%%~S"
    setlocal EnableDelayedExpansion
)
rem // Return string portion behind last predefined character:
echo(!LAST!
endlocal

endlocal
exit /B

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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