The source looks like this:

161/udp open  snmp
| snmp-brute: 
|   comstring1 - Valid credentials
|_  comstring2 - Valid credentials
161/udp open  snmp
| snmp-brute: 
|   comstring1 - Valid credentials
|_  comstring1 - Valid credentials

How to parse the above text so that it becomes:

08-28-2016_12-30|AAAAA|hostname01||comstring1-Valid credentials -- comstring1 - Valid credentials
08-28-2016_12-30|AAAAA|hostname02||comstring1-Valid credentials -- comstring1 - Valid credentials

The main problem is that code cannot grouping based on character "|" or "|_" , I've changed a lot of code but none were successful, such as:

awk '{ORS=($0 !~ "_"?FS:RS)}1'

Your script doesn't have to do anything special with the record- or field-separators. Given the sample input and output, the script has only to look for two of the four line types, i.e.,


(which is mostly separated by / characters), and

|   comstring1 - Valid credentials

which can be matched by a regular expression.

The script would have to match on the first line-type, e.g.,

/^.*\/.*\/.*\// {
    split($0, "/", fields);
    # ...more work needed :-)

and use split to chop it into an array based on the / character, and sub, substr and index to chop up the remainder of the line (the separate hostname and IP-address from "hostname01_192.168.1.1").

Once done, that gives you the variables that it would carry over into the printf done after extracting the message from the second line type. Doing that would be, perhaps 30 lines of script


Solution in TXR. The file data contains the data from the question, verbatim. reformat.txr contains this:

@port/udp open  snmp
| snmp-brute:@(skip)
@  (collect :gap 0)
|   @string - @val
@  (end)
|_  @endstring - @endval
@  (merge string string endstring)
@  (merge val val endval)
@  (repeat)
@date|@label|@host|@ipaddr|@(rep)@string - @val -- @(last)@string - @val@(end)
@  (end)


$ txr reformat.txr data
08-28-2016_12-30|AAAAA|hostname01||comstring1 - Valid credentials -- comstring2 - Valid credentials
08-28-2016_12-30|AAAAA|hostname02||comstring1 - Valid credentials -- comstring1 - Valid credentials

TXR is good for getting text extraction working over loosely structured data without putting a lot of work into it, and without putting a lot more work if the structure changes, or new cases have to be accomodated and such.

Coding TXR extraction jobs typically begins by copying and pasting actual sample data and output into a .txr file, then massaging that by adding the capture variables and directives. The working script emerges out of the data itself.

The structure of the data is still more or less recognizable in the resulting code.

  • you cannot using that approach, because the data is dynamic and format clearly different each other – nurulhudamustaqim Sep 2 '16 at 12:56
  • It works for the current sample data given in the question itself, and has some flexibility for somewhat different data, too. Please update the data. (However, note that it's not reasonable to update the data more than once or twice; the question is then too much of a "moving target" for stackexchange). – Kaz Sep 2 '16 at 13:32

Solved :)

awk '$0!~/(161|brute)/ {if ($0~/_/)ORS="\n"; else ORS="";print}'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.