sed从文件中提取多个可能的(?)值

时间:2010-09-16 08:01:50

标签: parsing shell sed

我的文件有多行,如下所示:

"<sender from="+919892000000" msisdn="+919892000000" ipAddress="" destinationServerIp="" pcfIp="" imsi="892000000" sccpAddress="+919895000005" country="IN" network="India::Airtel (Kerala)"
"<sender from="+919892000000" msisdn="+919892000000" ipAddress="" destinationServerIp="" pcfIp="" sccpAddress="+919895000005" country="IN" network="India::Airtel (Kerala)"

在第一个存在imsi,在第二行中,imsi不存在 对于以单词sender开头的每一行(文件中还有其他行),我想提取msisdn值和imsi值。如果imsi值不存在,我会打印出imsi:Unknown。

我尝试了以下但不起作用:

/sender / { /msisdn/ {s/.*msisdn=\"([^\"]*)?\".*/msisdn: \1/}; p; /imsi/ {s/.*imsi=\"([^\"]*)?\".*/imsi: \1/}; /imsi/! {s/.*/imsi: Unknown/}; p};

我错过了什么?

A

4 个答案:

答案 0 :(得分:1)

可以使用以下sed脚本完成此操作:

s/^.*sender .*msisdn="\([^"]*\)" .* imsi="\([^"]*\)".*$/msisdn: \1, imsi: \2/
t
s/^.*sender .*msisdn="\([^"]*\)".*$/msisdn: \1, imsi: Unknown/
t
d
  • 第一个s命令将打印全部 发件人行包含imsi 字段。
  • 第一个t命令将继续 如果是前一个下一行 命令成功。
  • 第二个t命令将全部打印 没有imsi字段的发件人行。
  • 第二个t命令将继续 如果是前一个下一行 命令成功。
  • d命令将删除所有其他命令 线。

要运行此脚本,只需将其复制到文件并使用sed -f脚本运行它。

答案 1 :(得分:1)

添加为什么我使用sed来解决这个特殊问题。以下是我用来创建数据结构以传递给awk的多行sed:

cat xmlEventLog_2010-03-23T* | 
sed -nr "/<event eventTimestamp/,/<\/event>/  {
/event /{/uniqueId/ {s/.*uniqueId=\"([^\"]+)\".*/\nuniqueId: \1/g}; /uniqueId/!  {s/.*/\nuniqueId: Unknown/}; p};
/payloadType / {/type/ {s/.*type=\"([^\"]+)\".*/payload: \1/g}; /type/! {s/.*protocol=\"([^\"]+)\".*/payload: \1/g}; p}; 

***/sender / { /msisdn/ {s/.*msisdn=\"([^\"]*)?\".*/msisdn: \1/}; p; /imsi/ {s/.*imsi=\"([^\"]*)?\".*/imsi: \1/}; p; /imsi/! {s/.*/imsi: Unknown/}; p};

/result /{s/.*value=\"([^\"]+)\".*/result: \1/g; p}; /filter code/{s/.*type=\"([^\"]+)\".*/type: \1/g; p}}" 

| awk 'BEGIN{FS="\n"; RS=""; OFS=";"; ORS="\n"} $4~/payload: SMS-MT-FSM-INFO|SMS-MT-FSM|SMS-MT-FSM-DEL-REP|SMS-MT-FSM-DEL-REP-INFO|SMS-MT-FSM-DEL-REP/ && $2~/result: Blocked|Modified/ && $3~/msisdn: +919844000011/ {$1=$1 ""; print}'

这解析了填充了如下事件的文件:

       <event eventTimestamp="2010-03-23T00:00:00.074" originalReceivedMessageSize="28" uniqueId="1280361600.74815_PFS_1_2130328364" deliveryReport="true">
            <result value="Allowed"/>
            <source name="MFE" host="PFS_1"/>
            <sender from="+919892000000" msisdn="+919892000000" ipAddress="" destinationServerIp="" pcfIp="" imsi="892000000" sccpAddress="+919895000005" country="IN" network="India::Airtel (Kerala)">
                    <profile code=""/>
                    <mvno code=""/>
            </sender>
            <recipients>
                    <recipient code="+919844000039" imsi="892000000" SccpAddress="+919895000005" country="IN" network="India::Airtel (Kerala)">
                    </recipient>
            </recipients>
            <payload>
                    <payloadType protocol="SMS" type="SMS-MT-FSM-DEL-REP"/>
                    <message signature="70004b7c9267f348321cde977c96a7a3">
                            <MailFrom value=""/>
                            <rcptToList>
                            </rcptToList>
                            <pduList>
                                    <pdu type="SMS_SS_REQUEST_IND" time="2010-07-29T00:00:00.074" source="SMSPROBE" dest="PCF"/>
                                    <pdu type="SMS_SS_REQ_HANDLING_STOP" time="2010-07-29T00:00:00.074" source="PCF" dest=""/>
                            </pduList>
                            <numberOfImages>0</numberOfImages>
                            <attachments numberOf="1">
                                    <attachment index="0" size="28" contentType="text/plain"/>
                            </attachments>
                            <emailSmtpDeliveryStatus value="" time="" reason=""/>
                            <pepId value="989350000109.989350000209.0.0"/>
                    </message>
            </payload>
            <filters>
            </filters>
    </event>

最多可能有10000个事件,例如每个文件上面的一个,并且会有数百个文件。 awk的结构输出应该是以下类型:

uniqueId: 1280361600.208152_PFS_1_1509661383
result: Allowed
msisdn: +919892000000
imsi: 892000000
payload: SMS-MT-FSM-DEL-REP
filter:

因此,我需要从发送者行提取2个值,从其他行提取不同的值。除了找到发送方行的部分(在过滤器中标记为***)之外,上述过滤器正确提取所有内容。所以我只想从结构的发送者行中提取2个项目。多次尝试都失败了。

答案 2 :(得分:1)

您对“msisdn”的匹配正在剥离“imsi”,因此始终采取负面匹配。只需将您的行复制到保留空间,执行“msisdn”处理,将保留空间交换回模式空间,然后进行“imsi”处理:

/sender / {h; /msisdn/ {s/.*msisdn=\"([^\"]*)?\".*/msisdn: \1/}; p;x; /imsi/ {s/.*imsi=\"([^\"]*)?\".*/imsi: \1/}; /imsi/! {s/.*/imsi: Unknown/};p}

答案 3 :(得分:0)

我用Perl来解决你的问题。

cat file | perl -n -e 'if (/sender.*msisdn="([^"]*)"(.*imsi="([^"]*)")?/) { print $1, " ", $3 || "unknown", "\n"; }'