问题
I have two text files using which i want to get output.txt as follows:
file1.txt:
Windows 1.36
Linux 2.78
MacOS 3.45
Ubuntu 4.12
FreePhysicalMemory 30.12
TotalVisibleMemorySize 48.00
CPULoadPercentage 2
file2.txt:
MacOS 6.39
Windows 4.42
Linux 5.76
Android 3.46
FreePhysicalMemory 31.65
TotalVisibleMemorySize 48.00
CPULoadPercentage 4
output.txt:
OPERATINGSYSTEM SERVER1 SERVER2
Windows 1.36 4.42
Linux 2.78 5.76
MacOS 3.45 6.39
Ubuntu 4.12 0.00
Android 0.00 3.46
FreePhysicalMemory 30.12 31.65
TotalVisibleMemorySize 48.00 48.00
CPULoadPercentage 2 4
But the problem here is, using following code i am getting output.txt like below, in which FreePhysicalMemory is being misplaced..:
code:
@echo off
setlocal EnableDelayedExpansion
set i=0
for /F "tokens=1,2" %%a in (file1.txt) do (
set /A i+=1
set order[!i!]=%%a
set info[%%a]=%%b
)
set total2=!order[%i%]!
set /A i-=1
set total1=!order[%i%]!
set /A i-=1
for /F "tokens=1,2" %%a in (file2.txt) do (
if defined info[%%a] (
set info[%%a]=!info[%%a]! %%b
) else (
set /A i+=1
set order[!i!]=%%a
set info[%%a]=0.00 %%b
)
)
set /A i+=1
set order[%i%]=%total1%
set /A i+=1
set order[%i%]=%total2%
(
echo OPERATINGSYSTEM SERVER1 SERVER2
for /L %%i in (1,1,%i%) do (
for /F %%a in ("!order[%%i]!") do (
for /F "tokens=1,2" %%b in ("!info[%%a]!") do (
set "os=%%a "
set "s1= %%b"
if "%%c" equ "" (
set "s2= 0.00"
) else (
set "s2= %%c"
)
echo !os:~0,22! !s1:~-5! !s2:~-9!
)
)
)
) > output.txt
output.txt:
OPERATINGSYSTEM SERVER1 SERVER2
Windows 1.36 4.42
Linux 2.78 5.76
MacOS 3.45 6.39
Ubuntu 4.12 0.00
FreePhysicalMemory 30.12 31.65
Android 0.00 3.46
TotalVisibleMemorySize 48.00 48.00
CPULoadPercentage 2 4
回答1:
Of course, this happen because your original request have two lines of totals, and your new request have three!
You must modify the program in order to include one line more of totals:
@echo off
setlocal EnableDelayedExpansion
rem Read info from file1
set i=0
for /F "tokens=1,2" %%a in (file1.txt) do (
set /A i+=1
set order[!i!]=%%a
set info[%%a]=%%b
)
rem Save totals
set total3=!order[%i%]!
set /A i-=1
set total2=!order[%i%]!
set /A i-=1
set total1=!order[%i%]!
set /A i-=1
rem Read/merge info from file2
for /F "tokens=1,2" %%a in (file2.txt) do (
if defined info[%%a] (
set info[%%a]=!info[%%a]! %%b
) else (
set /A i+=1
set order[!i!]=%%a
set info[%%a]=0.00 %%b
)
)
rem Return totals to end
set /A i+=1
set order[%i%]=%total1%
set /A i+=1
set order[%i%]=%total2%
set /A i+=1
set order[%i%]=%total3%
rem Format and output information
(
echo OPERATING SYSTEM SERVER1 SERVER2
for /L %%i in (1,1,%i%) do (
for /F %%a in ("!order[%%i]!") do (
for /F "tokens=1,2" %%b in ("!info[%%a]!") do (
set "os=%%a "
set "s1= %%b"
if "%%c" equ "" (
set "s2= 0.00"
) else (
set "s2= %%c"
)
echo !os:~0,22! !s1:~-5! !s2:~-9!
)
)
)
) > output.txt
回答2:
@ECHO OFF
SETLOCAL
SET spaces= x
SET "line="
FOR /f "delims==" %%a IN ('set list 2^>nul') DO SET "%%a="
FOR /f "tokens=1,2" %%a IN (file1.txt) DO SET list_%%a=%%b
FOR /f "tokens=1,2" %%a IN (file2.txt) DO (
IF defined list_%%a (CALL SET list_%%a=%%list_%%a%% %%b
) ELSE (SET list_%%a=0.00 %%b
)
)
FOR /f %%v IN (list.seq) DO IF NOT defined list_%%v SET list_%%v=0.00 0.00
FOR /f "tokens=1,2,3delims== " %%a IN ('set list 2^>nul') DO IF "%%c"=="" SET %%a=%%b 0.00
(
CALL :show L 22 "OPERATING SYSTEM" L 9 "SERVER1" L 12 "SERVER2"
FOR /f %%v IN (list.seq) DO (
FOR /f "tokens=2,3,4delims==_ " %%a IN ('set list_%%v') DO SET "suppdec="&CALL :show L 22 %%a R 7 %%b R 9 %%c&SET "list_%%v="
)
FOR /f "tokens=2,3,4delims==_ " %%a IN ('set list_ 2^nul') DO SET "suppdec="&CALL :show L 22 %%a R 7 %%b R 9 %%c
)>output.txt
TYPE output.txt
GOTO :EOF
:show
IF "%~3"=="" GOTO output
IF %1==L (SET column=%~3%spaces%) ELSE (SET column=%spaces:~0,-1%%~3%suppdec%)
IF %1==L (CALL SET line=%%line%%%%column:~0,%2%%) ELSE (CALL SET line=%%line%%%%column:~-%2%%)
SHIFT&shift&SHIFT
ECHO "%~3"|FIND "." >nul
IF ERRORLEVEL 1 (SET "suppdec= ") ELSE (SET "suppdec=")
GOTO show
:output
ECHO %line%
SET "line="
GOTO :eof
Where list.seq contains
Windows
Linux
Absent
MacOS
Ubuntu
Android
FreePhysicalMemory
TotalVisibleMemorySize
CPULoadPercentage
If an element is found in one file but not the other, 0.00 will appear for the missing data.
If a value does not contain a decimal, it will be shifted 2 spaces to align the unit column with the decimals.
Elements NOT appearing in the data files but that ARE mentioned in the list.seq file will appear with values 0.00
Elements appearing in the data files that are not mentioned in the list.seq file will appear in alphabetical order after those that DO appear in list.seq
回答3:
Here is an entirely different approach with the following features:
- The number of servers (files) is easily extensible. Simply add a new file to the list in the outer loop of the Load data section.
- The header for each server is derived from the file name by dropping the extension.
- The width of each server column is easily configurable
- The width of the OS label column is easily configurable
- Missing values are displayed as blank instead of a misleading 0
- OS labels are displayed in alphabetical order, followed by the summary rows.
- The number and order of summary rows at the end is easily configurable. Simply add or subtract values in the
lookupvariable.
I renamed FILE1.TXT, FILE2.TXT to SERVER1.TXT, SERVER2.TXT. I also copied SERVER1.TXT to SERVER3.TXT just so I could test value missing from previous column.
@echo off
setlocal enableDelayedExpansion
:: Clear any existing $ variables
for /f "delims==" %%A in ('"set $ 2>nul"') do set "%%A="
:: Load data
set "cnt=0"
set "blank= "
set "width=8"
set "labelWidth=22"
set "lookup= FreePhysicalMemory:2 TotalVisibleMemorySize:3 CPULoadPercentage:4"
for %%F in (server1.txt server2.txt server3.txt) do (
set "val=%blank%%%~nF"
set "$0.OPERATINGSYSTEM=!$0.OPERATINGSYSTEM! !val:~-%width%!"
for /f "tokens=1,2" %%A in (%%F) do (
set "test=!lookup:* %%A:=!"
if "!test!" equ "!lookup!" (set "prefix=$1.") else set "prefix=$!test:~0,1!."
for %%P in (!prefix!) do (
if not defined !prefix!%%A (
for /l %%N in (1 1 !cnt!) do set "%%P%%A=!%%P%%A! !blank:~-%width%!"
) else if "!%%A!" neq "!cnt!" (
set "%%P%%A=!%%P%%A! !blank:~-%width%!"
)
set "val=%blank%%%B"
set "%%P%%A=!%%P%%A! !val:~-%width%!"
)
set /a "%%A=cnt+1"
)
set /a cnt+=1
)
:: Print results
for /f "tokens=2* delims=.=" %%A in ('set $') do (
set "label=%%A%blank%"
echo !label:~0,%labelWidth%!%%B
)
-- OUTPUT --
OPERATINGSYSTEM SERVER1 SERVER2 SERVER3
Android 3.46
Linux 2.78 5.76 2.78
MacOS 3.45 6.39 3.45
Ubuntu 4.12 4.12
Windows 1.36 4.42 1.36
FreePhysicalMemory 30.12 31.65 30.12
TotalVisibleMemorySize 48.00 48.00 48.00
CPULoadPercentage 2 4 2
EDIT in response to OP comment
Here is a modified version that uses NULL for missing values and writes the output to a text file.
@echo off
setlocal enableDelayedExpansion
:: Clear any existing $ variables
for /f "delims==" %%A in ('"set $ 2>nul"') do set "%%A="
:: Load data
set "cnt=0"
set "blank= "
set "null= NULL"
set "width=8"
set "labelWidth=22"
set "lineWidth=0"
set "lookup= FreePhysicalMemory:2 TotalVisibleMemorySize:3 CPULoadPercentage:4"
for %%F in (server1.txt server2.txt server3.txt) do (
set "val=%blank%%%~nF"
set "$0.OPERATINGSYSTEM=!$0.OPERATINGSYSTEM! !val:~-%width%!"
for /f "tokens=1,2" %%A in (%%F) do (
set "test=!lookup:* %%A:=!"
if "!test!" equ "!lookup!" (set "prefix=$1.") else set "prefix=$!test:~0,1!."
for %%P in (!prefix!) do (
if not defined !prefix!%%A (
for /l %%N in (1 1 !cnt!) do set "%%P%%A=!%%P%%A! !null:~-%width%!"
) else if "!%%A!" neq "!cnt!" (
set "%%P%%A=!%%P%%A! !null:~-%width%!"
)
set "val=%blank%%%B"
set "%%P%%A=!%%P%%A! !val:~-%width%!"
)
set /a "%%A=cnt+1"
)
set /a cnt+=1, lineWidth+=width+1
)
:: Print results
(for /f "tokens=2* delims=.=" %%A in ('set $') do (
set "line=%%B !null:~-%width%!"
set "label=%%A%blank%"
echo !label:~0,%labelWidth%!!line:~0,%lineWidth%!
))>output.txt
来源:https://stackoverflow.com/questions/19739359/text-output-placement