3

I have a file (file1.csv) that has two values separated by commas. I need a way to remove the leading zero's from both values in one batch file.

So far I've used this:

@echo off
(for /f "tokens=*,* delims=0" %%a in (file1.csv) do echo(%%a)>stripped.txt

It works quite well although it only removes the zero's from the first number and not the second.

Sample from file1.csv:

00012345,00000012345 

00067890,00000067890

Sample from stripped.txt after using the above batch file:

12345,00000012345

67890,00000067890

Anyone have suggestions on how I can do the same for the number after the comma?

Hoh
  • 1,196
  • 1
  • 12
  • 30
Mike
  • 33
  • 2
  • Your code does not work at all for me. I get `,* delims=0" was unexpected at this time.` when I run it. – aphoria Aug 27 '14 at 18:58

2 Answers2

5

If you are willing to use a hybrid JScript/batch utility called REPL.BAT, then the solution can be as simple as:

type file.csv|repl "0*(\d\d*),0*(\d\d*)" "$1,$2" >stripped.csv

Not only is this REPL.BAT solution simple, it is also very efficient. It can process a large CSV quite quickly.

If you must have a pure batch solution, then here is one that does not use CALL or GOTO or delayed expansion, and it properly handles a value of 0. This will be significantly slower than the REPL.BAT solution, but I think it is the most efficient pure batch solution possible.

The first loop parses the line into two values.

Then there are two more loops for each value. The first strips the leading zeros, but it also appends an additional 0 value after a space so that it always returns a string, even if the value is 0. The last loop then returns either the original zero stripped value, or if it has been eliminated because it was 0, then it returns the appended 0 value.

@echo off
(for /f "delims=, tokens=1,2" %%A in (file.csv) do (
  for /f "delims=0 tokens=*" %%C in ("%%A 0") do for /f %%E in ("%%C") do (
    for /f "delims=0 tokens=*" %%D in ("%%B 0") do for /f %%F in ("%%D") do (
      echo %%E,%%F
    )
  )
))>stripped.csv

The code to strip leading zeros can be encapsulated in a function, and then it becomes more convenient to use. This is especially true if you have many values within the line to strip. But the CALL mechanism is quite slow. For this simple problem with two values to strip, it slows the solution down by more than a factor of 5.

@echo off
setlocal enableDelayedExpansion

(for /f "delims=, tokens=1,2" %%A in (file.csv) do (
  call Strip0 %%A A
  call Strip0 %%B B
  echo !A!,!B!
))>stripped.csv
exit /b

:strip0  ValueStr  [RtnVar]
::
:: Strip leading zeros from value ValueStr and store the result in vaiable RtnVar.
:: If RtnVar is not specified, then print the result to stdout.
::
for /f "delims=0 tokens=*" %%A in ("%~1") do for /f %%B in ("%%A 0") do (
  if "%~2" equ "" (echo %%B) else set "%~2=%%B"
)
exit /b

There is an advanced batch macro technique that can encapsulate the logic in a macro function without significantly slowing things down. See http://www.dostips.com/forum/viewtopic.php?f=3&t=1827 for background information about batch macros with arguments.

Here is a solution using a batch macro. It is 4 times faster than the CALL method.

@echo off

:: The code to define the macro requires that delayed expansion is disabled.
setlocal disableDelayedExpansion
call :defineStrip0

:: This example requires delayed expansion within the loop
setlocal enableDelayedExpansion
(for /f "delims=, tokens=1,2" %%A in (file.csv) do (
  %strip0% %%A A
  %strip0% %%B B
  echo !A!,!B!
))>stripped.csv
exit /b


:defineStrip0    The code below defines the macro.

:: Define LF to contain a linefeed character (0x0A)
set ^"LF=^

^" The above empty line is critical - DO NOT REMOVE

:: Define a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

::%strip0%  ValueStr  [RtnVar]
::
::  Strip leading zeros from string ValueStr and return the result in variable StrVar.
::  If RtnVar is not specified, then print the result to stdout.
::
set strip0=%\n%
for %%# in (1 2) do if %%#==2 (setlocal enableDelayedExpansion^&for /f "tokens=1,2" %%1 in ("!args!") do (%\n%
  for /f "delims=0 tokens=*" %%A in ("%%1") do for /f %%B in ("%%A 0") do (%\n%
    endlocal^&if "%%2" equ "" (echo %%B) else set "%%2=%%B"%\n%
  )%\n%
)) else set args=
exit /b
Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
1

EDIT: My first code was wrong! This version works ok:

@echo off
setlocal EnableDelayedExpansion

(for /f "tokens=1,2 delims=," %%a in (file1.csv) do (
   call :leftZero %%a first=
   call :leftZero %%b second=
   echo !first!,!second!
))>stripped.txt
goto :EOF

:leftZero
set num=%1
:nextZero
   if "%num:~0,1%" neq "0" goto endLeftZero
   set num=%num:~1%
goto nextZero
:endLeftZero
set %2=%num%
exit /B
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • I started down this path too, but it strips the trailing zeroes off the numbers in the second line. – aphoria Aug 27 '14 at 19:02