我需要从.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
答案 0 :(得分:1)
使用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 {进行转义{1}})。这将设置特殊变量\
,即输入记录分隔符,它告诉RS
如何根据指定的正则表达式将输入分解为记录。 (awk
然后引用正在处理的整个当前记录。)$0
) - -F'\n'
设置特殊变量-F
,输入字段分隔符,告诉FS
如何拆分每条记录到单个字段(awk
,$1
,...)$2
- 请参阅源代码中的注释。dict["Desc"]
语句从感兴趣的字段值合成所需的输出字符串。注意:使用了以下特定于GNU的非POSIX功能:
printf
值不仅仅是单个字符RS
函数,用于灵活的基于正则表达式的字符串替换(比POSIX gensub()
/ sub
函数更灵活)gsub
语句删除整个数组。答案 1 :(得分:0)
只是为了好玩,我觉得你的第一次awk
尝试并不遥远。您只需将字段分隔符设置为:
(-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
来打印一行,因为它将被调用2次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
语法有点神秘,但非常紧凑...