1

I have the following data table:

ssh     22/tcp  0.182286        # Secure Shell Login
linuxconf   98/tcp  0.000088 
tacnews    98/udp   0.000560    # TAC News

from which I wish to generate a CSV file in the following format:

ssh,22,tcp,Secure Shell Login
linuxconf,98,tcp,
tacnews,98,udp,Tac News

I am discarding the fractional decimal number and including the description without the '# ' if it exists.

I see the data as a bunch of fields (forgive the faux regex):

^{1}\s+{2}/{3}\s+{4}\s+# {5}$  

For which I would output:

{1},{2},{3},{5}  

What would be the most simplest and most appropriate tool to do this? I'd be grateful for help with the syntax to achieve this.

2

The best tool for something like this is probably sed, here is a working example using extended regular expressions:

sed -E 's:^([^ ]*)\s+([^/]*)/([^ ]*)\s+[^ ]*\s*#?\s*(.*):\1,\2,\3,\4:' file

Or if your input might be tab delimited:

sed -E 's:^([^[:space:]]*)\s+([^/]*)/([^[:space:]]*)\s+[^[:space:]]*\s*#?\s*(.*):\1,\2,\3,\4:' file

Output:

ssh,22,tcp,Secure Shell Login
linuxconf,98,tcp,
tacnews,98,udp,TAC News

Explanation

  • s::: use colon as the expression delimiter
  • ^([^ ]*) first capture group, match sequence of non-space characters at the beginning of the line
  • \s+ ignore space
  • ([^/]*) second capture group, match upto a slash
  • / ignore slash
  • ([^ ]*) third capture group, match sequence of non-space characters
  • \s+ ignore space
  • [^ ]* ignore decimal number
  • \s*#?\s* ignore space and optional hash
  • (.*) fourth capture group, the rest of the line
  • Thor thank you for the quick response aswell as the explanation. It's not quite working for me. I have tried on the nmap-services file but it's giving: ssh,22,tcp 0.182286 #,Shell Login I ran: sed -E 's:^([^ ]*)\s+([^/]*)/([^ ]*)\s+[^ ]*\s*#?\s*(.*):\1,\2,\3,\4:' nmap-services > nmap-services.csv – user1330734 Nov 10 '16 at 15:17
  • 1
    @user1330734: I have added an alternative that supports tab delimited input – Thor Nov 10 '16 at 15:22
1

I'd use perl: You have the regex sketched out, this fills in the gaps.

perl -lne '
    / (\S+)     \s+      # non-whitespace followed by whitespace
      (\d+)     \/       # digits followed by slash
      (\S+)     \s+      # non-whitespace followed by whitespace
      (\S+)     \s*      # non-whitespace followed by optional whitespace
      (?:\#\s)? (.*)     # possibly a hash+space and whatever follows
    /x and print "$1,$2,$3,$4,$5"' file

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.