2

Let's say I have this in my batch file:

set var1=12345

And I want to add commas in the first variable (var1) and save it to another variable (var2).

That means that the second variable (var2) should have this value: 12,345.

So If the first variable (var1) had this value: 123456789, the second one's (var2) value has to be 123,456,789.

Any ideas?

EDIT:

I don't want PowerShell commands because the don't work for me. Please write without PowerShell.

SomethingDark
  • 13,229
  • 5
  • 50
  • 55
Tom Lenc
  • 765
  • 1
  • 17
  • 41

7 Answers7

4

Another one!

@echo off
setlocal EnableDelayedExpansion

set "var1=%1"

echo First variable: %var1%


set "var2="
set "sign="
if "%var1:~0,1%" equ "-" set "sign=-" & set "var1=%var1:~1%"
for /L %%i in (1,1,4) do if defined var1 (
   set "var2=,!var1:~-3!!var2!"
   set "var1=!var1:~0,-3!"
)
set "var2=%sign%%var2:~1%"


echo Second variable: %var2%

If you want to increase the number of digits, just increase the number of groups in the for command to a value greater than 4.

Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • Yeah this works. And it's also the shortest script on this page :D But I'm still having problems... I will tell you later when I'll have some free time. – Tom Lenc Feb 24 '15 at 20:53
  • Oh nevermind I played around with the code and got exactly what I wanted. Thank you! :) – Tom Lenc Feb 25 '15 at 15:20
  • can the output look like this: 1 000 instead of this: 1,000 ? – Tom Lenc Feb 25 '15 at 20:52
  • 1
    Ooh - I like this one. Set the loop count to 2730 and put `if not defined var1 goto break` within the loop, and call it a day. It can then handle the maximum size string of digits, yet it still will be very fast. The GOTO doesn't completely short-circuit the FOR /L loop, but an empty loop of that size can complete in less than 10 msec. – dbenham Feb 25 '15 at 22:16
2

A bit tricky to do with pure batch. Here is an efficient solution that utilizes the :strlen function to determine the length of a string. The :showThousands function will work with any integer, positive or negative, with up to nearly 8191 digits. The function only modifies values that optionally start with -, and then the remainder consists only of digits.

@echo off
setlocal enableDelayedExpansion
for %%N in (
  1
  12
  123
  1234
  12345
  123456
  1234567
  123456789
  1234567890
  12345678901234567890
  -12345678901234567890
  fred
  123456.789
) do (
  set input=%%N
  call :showThousands input output
  echo !input! --^> !output!
)
exit /b


:showThousands  inVar  outVar
setlocal enableDelayedExpansion
set num=!%~1!
set "sign="
if %num:~0,1% equ - (
  set "sign=-"
  set "num=%num:~1%"
)
for /f "delims=0123456789" %%A in ("%num%") do goto :showThousandsReturn
call :strlen len num
if %len% leq 3 goto :showThousandsReturn
set /a end=len%%3
if %end% equ 0 set /a end=3
set /a start=(len-4)/3*3+end
for /l %%N in (%start% -3 %end%) do set "num=!num:~0,%%N!,!num:~%%N!"
:showThousandsReturn
endlocal & set "%~2=%sign%%num%"
exit /b


:strlen <resultVar> <stringVar>
(   
  setlocal EnableDelayedExpansion
  set "s=!%~2!#"
  set "len=0"
  for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
    if "!s:~%%P,1!" NEQ "" ( 
      set /a "len+=%%P"
      set "s=!s:~%%P!"
    )
  )
)
( 
  endlocal
  set "%~1=%len%"
  exit /b
)

-- OUTPUT --

1 --> 1
12 --> 12
123 --> 123
1234 --> 1,234
12345 --> 12,345
123456 --> 123,456
1234567 --> 1,234,567
123456789 --> 123,456,789
1234567890 --> 1,234,567,890
12345678901234567890 --> 12,345,678,901,234,567,890
-12345678901234567890 --> -12,345,678,901,234,567,890
fred --> fred
123456.789 --> 123456.789
Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
1

Batch is not a good language to do this sort of complex string manipulation in. For most people I would recommend using PowerShell to do the heavy lifting.

for /f %%a in ('powershell -c "'{0:N0}' -f %var1%"') do set var2=%%a

If you need a purely batch solution, you can do it iteratively with a lot more code. This example works on 32-bit integers. For larger numbers or floating point numbers see @dbenham's answer.

thousands.cmd

@echo off
::   in:  Integer value (must fit into 32 bits)
::   Out: Prints that value with commas after each 3 digits

setlocal
set /a num = %1
set output=

:: Check for trivial zero case and any non-number string input
if {%num%}=={0} (
  echo 0
  goto :eof
)

:nextgroup
if %num:-=% LSS 1000 goto :lastgroup
set output=,%num:~-3%%output%
set /a num = %num% / 1000
goto :nextgroup

:lastgroup
set output=%num%%output%

endlocal && echo.%output%

Examples:

> thousands.cmd 1000
1,000

> thousands.cmd -876543210
-876,543,210

> thousands.cmd 0
0

> thousands.cmd -512
-512

> thousands.cmd fred
0
Ryan Bemrose
  • 9,018
  • 1
  • 41
  • 54
1
set var2=%var1:~0,-3%,%var1:~-3%
SomethingDark
  • 13,229
  • 5
  • 50
  • 55
  • 1
    This is the correct answer to the second edit posted. But the original question keeps fundamentally changing. – Ryan Bemrose Feb 24 '15 at 16:55
  • A thousands separator is _way_ harder than just inserting a string. This is going to take me a bit, especially since I am probably going to have to end up taking decimals into account (they haven't been mentioned yet, but let's face it: they will be). – SomethingDark Feb 24 '15 at 16:58
0

SET var2=%var1%,5 should do the job.

MBaas
  • 7,248
  • 6
  • 44
  • 61
  • Ok.. But what if the nuber was randomly changing? I want to put the comma after the second number... For example if I have those numbers: 256575 The result should be this: 25,6575 – Tom Lenc Feb 24 '15 at 16:21
  • @TomLenc - Will the comma always go after the second digit? – SomethingDark Feb 24 '15 at 16:23
  • I actually want to add a comma after the third number but from the back(backwards). So. I have this number: 2536, I want this: 2,536 ; I have this number: 25366, I want this: 25,366 . Hope you understand my english... – Tom Lenc Feb 24 '15 at 16:24
  • None of your examples up to this point have matched that pattern so far. 125 would have no commas, 3575 would be 3,575, and 256575 would be 256,575. – SomethingDark Feb 24 '15 at 16:31
  • Yeah that's exactly what I wanted. Could you please do this for me? The numbers I use have more than 7 digits. – Tom Lenc Feb 24 '15 at 16:35
  • @TomLenc - sure, just correct your question first, or else you'll keep getting wrong answers. – SomethingDark Feb 24 '15 at 16:40
  • Back again on the PC after family-distraction. After all these refinements of the question, you've probably reached the end of what pure DOS can do. If you can't use powershell, maybe TakeCommand is possible? (It has the `@Comma`-Function which will do what you need - see help @ http://jpsoft.com/help/f_comma.htm ) – MBaas Feb 24 '15 at 18:03
0

quick and easy solution. you can save this as a batch and call it with your number as the argument, or embed it in whatever script you are making.

explanation:

if the input val is greater than 999 then set "newval" to a comma, and last three digits of "val" and then trim the last three digits off of val.
loop until val is no longer more than 3 digits, dump the output.

setlocal
set val=%1
:loop
if %val% GTR 999 (set newval=,%val:~-3%%newval% & set val=%val:~0,-3%
 goto loop
) 
echo %val:~-3%%newval%

and if you really need to deal with negative numbers, use this instead.

setlocal
set val=%1
if %val% LSS 0 ( set "sign=-" & set "val=%val:~1%" )

:loop
if %val% GTR 999 (set newval=,%val:~-3%%newval% & set val=%val:~0,-3%
 goto loop
) 

echo %sign%%val:~-3%%newval%

sure, this doesnt handle bad inputs, but it is short and sweet.

0

A bit late to the party I know but this may be of use to late arrivals at this thread like myself. This method employs basic SET substitution techniques. It also supports negative integers with leading [-] sign. It is a static solution in that it applies an arbitrary maximum input digit size but this can be modified to suit requirements. For those interested in performance, it is quicker than FOR loop solutions.

::  Sample code is for max 21 (-20) digit numbers 
::    For larger numbers increase pad size and extend the "preset commas" instruction
::       with leading " %var1:~-NN,3%, " where NN increments by 3
::    The only limit would seem to be variable VAR2 maximum size
::  Note: no size check nor numeric integrity is applied, if input size exceeds
::        design max top digits are simply lost

rem Left pad input with 20 [max-1] characters of your choice [except comma]
rem       12345678901234567890
 set var1=####################%1
rem preset comma separators
 set var2=%var1:~-21,3%,%var1:~-18,3%,%var1:~-15,3%,%var1:~-12,3%,%var1:~-9,3%,%var1:~-6,3%,%var1:~-3%
rem remove redundant chars
 set var2=%var2:#,=%
 set var2=%var2:#=%
    rem only needed if -nn negative numbers are to be supported
    set var2=%var2:-,=-%
 ECHO %1 ==^> %var2%