我在使用此awk命令时遇到问题。它不会产生我想要给出这个输入文件的结果。请有人帮我这个吗?
我正在寻找"班级:"价值" ABC"。当我找到ABC时。我喜欢将与userName / servicelist / hostlist和端口号关联的值分配给变量。 (请参阅输出部分)
awk -v q="\"" '/ABC/{f=1;c++}
f && /userName|serviceList|hostList|portNumber/
{sub(":",c"=",$1);
print $1 q $3 q
}
/port:/{f=0;print ""}' filename
该文件包含以下输入
Instance: Ths is a test
Class: ABC
Variables:
udpRecvBufSize: Numeric: 8190000
userName: String:test1
pingInterval: Numeric: 2
blockedServiceList: String:
acceptAllServices: Boolean: False
serviceList: String: ABC
hostList: String: 159.220.108.3
protocol: String: JJJJ
portNumber: Numeric: 20001
port: String: RTR_LLLL
Children:
Instance: The First Server in the Loop
Class: Servers
Variables:
pendout: Numeric: 0
overflows: Counter: 0
peakBufferUsage: Numeric: 100
bufferPercentage: Gauge: 1 (0,100)
currentBufferUsage: Numeric: 1
pendingBytesOut: Numeric: 0
pendingBytesIn: Numeric: 1
pingsReceived: Counter: 13597
pingsSent: Counter: 87350
clientToServerPings: Boolean: True
serverToClientPings: Boolean: True
numInputBuffers: Numeric: 10
maxOutputBuffers: Numeric: 100
guaranteedOutputBuffers: Numeric: 100
lastOutageDuration: String: 0:00:00:00
peakDisconnectTime: String:
totalDisconnectTime: String: 0:00:00:00
disconnectTime: String:
disconnectChannel: Boolean: False
enableDacsPermTest: Boolean: False
enableFirewall: Boolean: False
dacsPermDenied: Counter: 0
dacsDomain: String:
compressPercentage: Gauge: 0 (0,100)
uncompBytesSentRate: Gauge: 0 (0,9223372036854775807)
Instance: Ths is a test
Class: ABC
Variables:
udpRecvBufSize: Numeric: 8190000
userName: String:test2
pingInterval: Numeric: 4
blockedServiceList: String:
acceptAllServices: Boolean: False
serviceList: String: DEF
hostList: String: 159.220.111.2
protocol: String: ffff
portNumber: Numeric: 20004
port: String: JJJ_LLLL
Children:
这是我要找的输出。分配变量
userName1="test1"
serviceList1="ABC"
hostList1="159.220.108.3"
portNumber1="2001"
userName2="test2"
serviceList2="DEF"
hostList2="159.220.111.2"
portNumber2="2004"
答案 0 :(得分:2)
如果您打算分配一系列变量,那么您可以一次性提取您感兴趣的特定部分,而不是一次解析整个文件。例如:
$ awk -F'\n' -v RS= -v record=1 -v var=userName 'NR == record { for (i=1; i<=NF; ++i) if (sub("^\\s*" var ".*:\\s*", "", $i)) print $i }' file
test1
$ awk -F'\n' -v RS= -v record=1 -v var=serviceList 'NR == record { for (i=1; i<=NF; ++i) if (sub("^\\s*" var ".*:\\s*", "", $i)) print $i }' file
ABC
awk脚本可以放在shell函数中并像这样使用:
parse_file() {
record=$1
var=$2
file=$3
awk -F'\n' -v RS= -v record="$record" -v var="$var" 'NR == record {
for (i=1; i<=NF; ++i) if (sub("^\\s*" var ".*:\\s*", "", $i)) print $i
}' "$file"
}
userName1=$(parse_file 1 userName file)
serviceList1=$(parse_file 1 serviceList file)
# etc.
答案 1 :(得分:0)
$ awk -F: -v q="\"" '/Class: ABC/{f=1;c++;print ""} \
f && /userName|serviceList|hostList|portNumber/ \
{gsub(/ /,"",$1); \
gsub(/ /,"",$3); \
print $1 c "=" q $3 q} \
/Children:/{f=0}' vars
userName1="test1"
serviceList1="ABC"
hostList1="159.220.108.3"
portNumber1="20001"
userName2="test2"
serviceList2="DEF"
hostList2="159.220.111.2"
portNumber2="20004"
它将为每个&#34;类增加计数器:ABC&#34;模式并设置一个标志。将格式化并打印所选条目,直到块的终端模式。这限制了两种模式之间的背景。
答案 2 :(得分:0)
假设bash 4.0或更新版本,根本不需要awk:
flush() {
if (( ${#hostvars[@]} )); then
for varname in userName serviceList hostList portNumber; do
[[ ${hostvars[$varname]} ]] && {
printf '%q=%q\n' "$varname" "${hostvars[$varname]}"
}
done
printf '\n'
fi
hostvars=( )
}
class=
declare -A hostvars=( )
while read -r line; do
[[ $line = *"Class: "* ]] && class=${line#*"Class: "}
[[ $class = ABC ]] || continue
case $line in
*:*:*)
IFS=$': \t' read varName varType value <<<"$line"
hostvars[$varName]=$value
;;
*"Variables:"*)
flush
;;
esac
done
flush
值得注意的要点:
hostvars
关联数组中(其他语言可能称为&#34; map&#34;或&#34; hash&#34;),即使我们&# 39;只打印定义为感兴趣的四个名称。因此可以定义更有趣的逻辑,其组合多个变量来决定输出什么,&amp; c。flush
函数在循环外部定义,因此可以在多个位置使用 - 无论是在启动新块时(如检测到的,在此处,通过查看Variables:
),以及在档案结尾。serviceList
包含$(rm -rf /*)'$(rm -rf /*)'
的情况(存在重复以逃避单引号); printf %q
使这很容易,而awk没有等价物。答案 3 :(得分:0)
TXR中的解决方案:
@(collect) @(skip)Class: ABC Variables: @ (gather) userName: String:@user serviceList: String: @servicelist hostList: String: @hostlist portNumber: Numeric: @port @ (until) Children: @ (end) @(end) @(deffilter shell-esc ("\"" "\\\"") ("$" "\\$") ("`" "\\'") ("\\" "\\\\")) @(output :filter shell-esc) @ (repeat :counter i) userName@(succ i)="@user" serviceList@(succ i)="@servicelist" hostList@(succ i)="@hostlist" portNumber@(succ i)="@port" @ (end) @(end)
执行命令
$ txr data.txr data userName1="test1" serviceList1="ABC" hostList1="159.220.108.3" portNumber1="20001" userName2="test2" serviceList2="DEF" hostList2="159.220.111.2" portNumber2="20004"
注1:如果数据可能包含目标语言中引号之间特殊的字符,则必须转义。 from tkinter import *
Window = Tk()
import make_entry
make_entry.Create()
Window.mainloop()
过滤器基于生成的变量赋值是shell语法的假设。它很容易被替换。
注2:该代码假定每个shell-esc
都包含所有必需的变量。如果缺少某些内容,它将无法正常工作,有两种方法可以通过调整Class: ABC
行来解决这个问题:
失败:
@(gather :vars (user servicelist hostlist port))
含义:如果未收集这四个变量中的任何一个,则失败。结果是跳过了缺少变量的整个@(gather)
部分。
默认缺失:
@(gather :vars (user (servicelist "ABC") hostlist port))
含义:必须收集四个变量Class: ABC
,user
,servicelist
和hostlist
。但是,如果缺少port
,则会获得默认值serviceList
,并将其视为已找到。