remyremy
remyremy

Reputation: 3758

How to replace in a text file all values in GB by values in MB?

I need to read a file and replace a value in GB by a value in MB. The value is not always in GB and most of the time a decimal. The only way I found was the following:

for /F "tokens=1,2,3,4 delims=," %%A in (file.log) do (
    echo.%%D|findstr "GB Available" >nul 2>&1
    if errorlevel 0 if not errorlevel 1 (
        set value=%%D 
        echo value:!value!          REM looks like "Available= 12.53GB"
        set value_short=!value:~11!
        set value_short=!value_short: GB=!   REM looks like "12.53"
        echo value_short:!value_short!
        set /a value_converted=!value_short:.=!*10
        echo value_converted:!value_converted! MB REM looks like "1253 MB"
        set "line=%%D"
        set "line=!line: !value_short!=!value_converted!!"
        echo LINE: !line! REM Need to have something like: "Available= 1253MB"
    )
    if errorlevel 1 (
        echo no 
    )
)   

Unfortunately set "line=!line: !value_short!=!value_converted!!" doesn't work, I also tried with % instead of ! but it's not working. What is wrong with this line?

The main goal is to have values in MB in my file and for that I read the file and write the lines in MB without touching them in a new file, and re-write the lines with GB by converting them. If you have a simpler way, it's more than welcome!

Upvotes: 0

Views: 44

Answers (1)

dbenham
dbenham

Reputation: 130849

You are assuming the GB value always has 2 decimal places, and also that the value unit uses multiples of 1000 and not multiples of 1024. I am going to assume that is correct.

There is a simpler notation for conditional execution using the && (success) and || (failure) operators.

Your FINDSTR search is incorrect. It will match any line that contains GB or Available. You want and instead. I would use a regular expression search `"^Available=.*GB$".

Your REMark claims the source value is 12.53GB, but your code implies it is 12.53 GB. I'm going to assume your code is correct and there is a space before the GB. Your code also assumes there is always a space before the number. I'm also going to assume that is correct.

Your failing line needs two layers of variable expansion. The search and replace terms must be expanded before the outer variable expansion. %var% would work if you were not in a code block, but you are, so it won't. The solution is to transfer the values to FOR variables.

for %%A in ("!value_short!") do for %%B in ("!value_converted!") do set "line=!line:%%~A=%%~B!"

If either value contained * or ? then you would have to switch to using FOR /F with a ("string") value.

But there is a much simpler way to accomplish your task.

for /F "tokens=1-4 delims=," %%A in (file.log) do (
  for /f "tokens=1-4 delims=. " %%a in ("%%D") do if "%%a"=="Available=" if "%%d"=="GB" (
    set "line=%%a %%b%%c0 MB"
    echo !line!
  ) else (
    echo no 
  )
)   

The above only fixes your existing code - it does not replace any values in your original file.

I wouldn't use any of the above pure batch to modify the file. Instead, I would use a hybrid JScript/batch utility called REPL.BAT that performs a regular expression search/replace on stdin and writes the results to stdout. It is pure script that will run natively on any Windows machine from XP onward.

type "file.log" | repl "(Available= )([0-9]+)\.([0-9][0-9]) GB" "$1$2$30 MB" >"file.log.new"
move /y "file.log.new" "file.log" >nul

Upvotes: 1

Related Questions