How to clean up masscan output (-oL)

2019-03-02 07:47发布

问题:

I have a problem with the output produced by the masscan utility with the -oL options ("grep-able" output); for instance, it outputs this:

Host: 143.137.155.7 ()  Ports: 80/open/tcp////
Host: 177.105.21.41 ()  Ports: 8080/open/tcp////
Host: 187.78.236.98 ()  Ports: 80/open/tcp////
Host: 177.137.76.220 () Ports: 8080/open/tcp////
Host: 177.105.10.112 () Ports: 9000/open/tcp////
Host: 191.232.34.9 ()   Ports: 80/open/tcp////
Host: 179.55.65.144 ()  Ports: 80/open/tcp////
Host: 177.83.203.147 () Ports: 8080/open/tcp////
Host: 177.182.50.124 () Ports: 8000/open/tcp////

The above is neither very readable nor easy to understand.

How can I use Linux command-line utilities, e.g. sed, awk, or grep, to output something as follows, using the file above?

143.137.155.7:80
177.105.21.41:8080
187.78.236.98:80
177.137.76.220:8080
177.105.10.112:9000

回答1:

How about

sed 's/^Host: \([0-9.]*\).*Ports: \([0-9]*\).*$/\1:\2/g'

Explanation:

  • s/regex/replacement/ substitutes regex with replacement
  • ^ matches the start of the string
  • Host: matches itself
  • [0-9.] is a character range that matches the digits 0 to 9 and .
  • [0-9.]* matches zero or more digits/dots
  • \([0-9.]*\) makes the matched IP address available in the replacement as \1
  • . matches any single character
  • .* matches zero or more single characters (i.e. any string)
  • Ports: matches itself
  • \([0-9]*\) matches a string of digits and makes it available as \2
  • .*$ matches the rest of the string

The flag g at the end applies the replacement to all matches rather than the first match on each line. In this case, there can only be one match (the entire line), so the flag doesn't do anything. I type it out of habit.



回答2:

While Tom's answer is probably the best one for the job, it never hurts to have other options.

Using awk and cut:

awk 'OFS=":" {print $2,$5}' | cut -d/ -f-1

There is almost certainly a more efficient way to do this entirely in awk but I am not sure how exactly.



回答3:

awk can take regex as a delimiter. Split on either / or 1+ spaces and then print the columns.

awk -F '[/ ]+' '{print $2 ":" $5}'


回答4:

awk  -F'[ /]' '{print $2":"$(NF-6)}/9000/{exit}' file

143.137.155.7:80
177.105.21.41:8080
187.78.236.98:80
177.137.76.220:8080
177.105.10.112:9000