来自xml解析的awk语句中的substr

时间:2014-11-01 23:55:55

标签: xml bash awk xml-parsing substr

链接到原始问题:bash script extract XML data into column format,现在进行修改和解释 - >

这行代码中的某些内容不正确,我相信它与substr部分有关,那是因为我没有完全理解,并且想学习如何更好地理解它。是的,我查看了文档,但没有完全点击。一些例子和一个答案真的很有帮助。

awk -F'[<>]' 'BEGIN{a["STKPR"]="Prod";a["STKSVBLKU"]="Prod";a["STKSVBLOCK"]="Prod";a["STKSVBLK2"]="Test";} /Name/{name=$3; type=a[substr(name,length(name))]; if (length(type)==0) type="Test";} /SessionHost/+/Host/{print type, name, $3;}'|sort -u

这一点:

type=a[substr(name,length(name))]; if (length(type)==0) type="Test";

这是xml格式,每个位都是包含主机名和IP的每个主机的块。

<?xml version="1.0"?>
<Connection>
  <ConnectionType>Putty</ConnectionType>
  <CreatedBy>Someone</CreatedBy>
  <CreationDateTime>2014-10-27T11:53:32.0157492-04:00</CreationDateTime>
  <CredentialConnectionID>9F3C3BCF-068A-4927-B996-CA52154CAE3B</CredentialConnectionID>
  <Description>Red Hat Enterprise Linux 5 (64-bit)</Description>
  <Events>
    <OpenCommentPrompt>true</OpenCommentPrompt>
    <WarnIfAlreadyOpened>true</WarnIfAlreadyOpened>
  </Events>
  <Group>PATH/TO/GROUP/NAME</Group>
  <ID>f2007f03-3b33-47d3-8335-ffd84ccc0e6b</ID>
  <MetaInformation />
  <Name>STKSPRDAPP01111</Name>
  <OpenEmbedded>true</OpenEmbedded>
  <PinEmbeddedMode>False</PinEmbeddedMode>
  <Putty>
    <AlwaysAskForPassword>true</AlwaysAskForPassword>
    <Domain>DOMAIN</Domain>
    <FontSize>12</FontSize>
    <Host>10.0.0.111</Host>
    <Port>22</Port>
    <PortFowardingArray />
    <TelnetEncoding>IBM437</TelnetEncoding>
  </Putty>
  <Stamp>85407098-127d-4d3c-b7fa-8f174cb1e3bd</Stamp>
  <SubMode>2</SubMode>
  <TemplateName>SSH-PerUserCreds</TemplateName>
</Connection>

我想要做的是与上面引用的链接类似。但在这里我要匹配 - &gt;

BEGIN{a["STKPR"]="Prod";a["STKSVBLKU"]="Prod";a["STKSVBLOCK"]="Prod";a["STKSVBLK2"]="Test";

以及所有其余的作为测试。最好阅读上一篇文章,以帮助使这一点更容易理解。谢谢。

2 个答案:

答案 0 :(得分:2)

由于此处的密钥长度不同,因此substr方法不是最佳方法。尝试:

awk -F'[<>]' '/Name/{n=$3;t="Test"; if(n ~ /^STKPR/) t="Prod"; if (n ~/^STKSVBLKU/) t="Prod"; if (n ~/^STKSVBLOCK/) t="Prod"} /SessionHost/+/Host/{print t, n, $3;}' sample.xml |sort -u
Test STKSPRDAPP01111 10.0.0.111

如何运作

在这种情况下,由t表示的类型是根据一系列if语句设置的。从上面的代码中可以看出:

t="Test"
if (n ~ /^STKPR/) t="Prod"
if (n ~ /^STKSVBLKU/) t="Prod" 
if (n ~ /^STKSVBLOCK/) t="Prod"

通过设置t="Test"Test成为默认值:除非另一个语句匹配,否则类型将为Test。如果以下语句查看以主机名开头的字符串,并且如果匹配,则将类型t设置为新值。 (当正则表达式以^开头时,这意味着后面的内容必须在字符串的开头匹配。)

使用发烧友正则表达式的替代方案

由于以上三个if语句都是针对Prod类型的,因此如果您愿意,可以将其中三个重新排列为:

t="Test"
if (n ~ /^STK(PR|SVBLKU|SVBLOCK)/) t="Prod"

(金属化:固定不匹配的括号括号)

答案 1 :(得分:1)

substr部分生成一个包含字符串最后一个字符的字符串。这是因为从位于字符串末尾的位置name开始采用字符串length(name)的子字符串,并且因为substr从1开始编制索引。

要匹配整个字符串,您可以使用变量name,而不是使用substr处理它。

/Name/ { name=$3; type=a[name]; if (length(type)==0) type="Test"; }