Text output placement

走远了吗. 提交于 2019-12-13 08:24:09

问题


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 lookup variable.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!