从txt文件中提取数据,得到简洁的输出

2024-10-01 11:19:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要从一个.txt文件中提取一些信息并获得一行简洁的输出 输出应如下所示: Display 1 - VMware SVGA 3D - 1600 x 900 x 32 bit @ 60 Hz - Primary Device

文本文件包含以下信息:

ws_diag 5.3.0 build-1427931
Device \\.\DISPLAY1
   Desc = "VMware SVGA 3D"
   Mode = 1555 x 794 x 32-bit @ 60Hz
   Bounds = 0,0  1555,794
   Flags = PRIMARY_DEVICE, ATTACHED_TO_DESKTOP
Device \\.\DISPLAY2
   Desc = "VMware SVGA 3D"
   Flags = 0x00000000
Device \\.\DISPLAYV1
   Desc = "RDPDD Chained DD"
   Flags = MIRRORING_DRIVER, TS_COMPATIBLE
Device \\.\DISPLAYV2
   Desc = "RDP Encoder Mirror Driver"
   Flags = MIRRORING_DRIVER, TS_COMPATIBLE
Device \\.\DISPLAYV3
   Desc = "RDP Reflector Display Driver"
   Flags = MIRRORING_DRIVER, TS_COMPATIBLE
monitor-info.txt (END) 

到目前为止,我的情况是:

import sys
file = open(monitor-info.txt[1])
while 1:
    line = file.readline()
    tpl = line.split(":")
    if tpl[0] == "Desc":
        var = tpl[0]
    if tpl[1] == "Mode":
        print var, tpl[1]
    if tpl[2] == "Flag":
        var = tpl[2]
    print var
       if not line:
        break

我也试过awk

awk -F: '/^Device/{v=$2}/^Desc/{print v $2}/^Mode/{print v$3}/^Flags/{print v$4}' output_file.txt

Tags: txtifmodevardevicedriverdesccompatible
2条回答

只是为了好玩,我想你的第一次尝试已经不远了。您只需将字段分隔符设置为:-F:),而它应该是=。你知道吗

也许你可以试试:

awk 'BEGIN{FS="="; OFS=" - "; desc=""}function display(){print dev, desc, flags}/Device/{if(desc!="") display(); desc=""; flags=""; dev=$0; gsub("Dev.*PLAY", "Display ", dev)}/Desc/{desc=$2}/Flags/{flags=$2}END{display}'

它的作用是:

  • 在开始时,将字段分隔符设置为=,并将输出字段分隔符设置为-(用于格式化)
  • 定义一个函数display来打印一行,因为它将被调用两次
  • 如果行包含Device,则打印前面的设备(如果有),存储设备的id并重置所有其他变量
  • 如果行包含Desc(或Mode),则将第二个字段存储在相应的变量中
  • 在文件末尾,打印最后一个设备

所有这些都会产生:

Display 1 - "VMware SVGA 3D" - PRIMARY_DEVICE, ATTACHED_TO_DESKTOP
Display 2 - "VMware SVGA 3D" - 0x00000000
Display V1 - "RDP Encoder Mirror Driver" - MIRRORING_DRIVER, TS_COMPATIBLE
Display V2 - "RDP Encoder Mirror Driver" - MIRRORING_DRIVER, TS_COMPATIBLE
Display V3 - "RDP Encoder Mirror Driver" - MIRRORING_DRIVER, TS_COMPATIBLE

awk语法有点晦涩,但非常简洁。。。你知道吗

对于GNU awk

gawk -F'\n' -v RS='Device \\\\\\\\.\\\\' '
    NF > 2 { # ignore the extraneous very first line
      delete dict # delete dictionary from previous record
      dict["Device"] = $1 # store device name
      for (i=2;i<NF;++i) { # store other fields in dict.
        split($i, tkns, / = /) # split into field name (e.g., "Desc") and value 
          # clean up strings (remove leading spaces from field name, remove
          # double quotes from value, and store in dictionary.
        dict[gensub(/^ +/, "", "", tkns[1])] = gensub(/"/, "", "g", tkns[2])
      }
        # Output desired fields, using the dictionary.
      printf "%s - %s - %s - %s\n", dict["Device"], dict["Desc"], dict["Mode"], dict["Flags"]
    }
  ' file

基本方法:

  • 将输入拆分为记录,每个记录包含与给定显示相关的所有行:-v RS='Device \\\\\\\\.\\\\'(请注意,输入中的每个文字\必须用3\转义)。这将设置特殊变量RS,即输入记录分隔符,它告诉awk如何根据指定的正则表达式将输入拆分为记录。($0然后引用正在处理的整个当前记录。)
  • 每条记录按行(-F'\n')--F设置特殊变量FS,即输入字段分隔符,它告诉awk如何将每条记录拆分为单独的字段($1$2,…)
  • 然后建立一个字段值字典,这样就可以通过字段名来引用值,例如dict["Desc"]-请参阅源代码中的注释。你知道吗
  • 最后,一个printf语句从感兴趣的字段值合成所需的输出字符串。你知道吗

注意:使用了以下特定于GNU的非POSIX特性:

  • 不仅仅是单个字符的RS
  • 用于灵活的、基于regex的字符串替换的gensub()函数(比POSIX sub/gsub函数更灵活)
  • 使用delete语句删除整个数组。你知道吗

相关问题 更多 >