问题
Link to the original question: bash script extract XML data into column format and now for a modification and explanation ->
Something within this line of code is not correct and I believe it is with the substr portion and that would be because I don't have a full understanding and would like to learn HOW better to understand it. Yes I have looked at documentation and its not fully clicking. A couple examples as well as an answer would really be helpful.
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
This bit here:
type=a[substr(name,length(name))]; if (length(type)==0) type="Test";
Here is the xml format which each bit is a block for each host that contains the hostname and 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>
What I want to do is similar to the referenced link above. But here I want to match -->
BEGIN{a["STKPR"]="Prod";a["STKSVBLKU"]="Prod";a["STKSVBLOCK"]="Prod";a["STKSVBLK2"]="Test";
and all of the rest as Test. Best to read the previous post to help make this one more understandable. Thank you.
回答1:
Because your keys here are of different length, the substr
approach is less than optimal. Try:
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
How It Works
In this case, the type, denoted by t
, is set according to a series of if
statements. From the above code, they are:
t="Test"
if (n ~ /^STKPR/) t="Prod"
if (n ~ /^STKSVBLKU/) t="Prod"
if (n ~ /^STKSVBLOCK/) t="Prod"
By setting t="Test"
, Test
becomes the default: the type will be Test
unless another statement matches. If of the following statements looks at the string that begins the host name and, if there is a match, sets type t
to a new value. (When a regular expression begins with ^
, that means that what follows must match at the beginning of the string.)
Alternative using fancier regular expressions
Since the above three if
statements are all for the Prod
type, the three of them could, if you preferred, be rearranged to:
t="Test"
if (n ~ /^STK(PR|SVBLKU|SVBLOCK)/) t="Prod"
(metalcated: Fixed unmatched parentheses bracket)
回答2:
The substr
portion produces a string containing the last character of the string. This is because it is taking a substring of string name
starting at the position length(name)
going to the end of the string, and because substr
is indexed starting at 1.
To match whole strings you can use your variable name
rather than processing it with substr
.
/Name/ { name=$3; type=a[name]; if (length(type)==0) type="Test"; }
来源:https://stackoverflow.com/questions/26694555/substr-in-awk-statement-from-xml-parse