简体   繁体   中英

How to get values between two numbers which is a string and separated by “-” symbol in python?

SO, the problem i am trying to solve is to categorise all the port numbers from 0 to 65535. i got a material which almost solves the problem. i have a csv file(coma seperated), which has two columns where one column is port number and other column is its Service Name (classification). in some columns of port number i have a range ie "100-200" which is a string.

Eg:-

Service Name   Port Number

pt-tls              271
Unassigned          272-279
http-mgmt           280
personal-link       281
cableport-ax        282
rescap              283
corerjd             284
Unassigned          285
fxp                 286
k-block             287
Unassigned          288-307
novastorbakcup      308

now in raw 2 and 11 there is a range. ie 272 to 279 and 288 to 307.
how to convert this into port numbers and mapped to the same service name. the result should looks like.

Service Name Port Number

pt-tls              271
Unassigned          272
Unassigned          273
Unassigned          274
Unassigned          275
Unassigned          276
Unassigned          277

I have tried

t= []

for i in range(data["Port Number"].shape[0]):
    #print(i)
    t.append(str(data["Port Number"][i]).split("-"))
    for p in t:
        if len(p)>1:
            t.append(range(int(p[0]),int(p[1])))
            print(range(int(p[0]),int(p[1])))
            #t.append(range())
        else: t.append(p)

The above code takes a lot of time. Is there any elegant way to solve this problem.

If there is any material which has already mapped ports please include in your answer.

Given the code you already wrote, I doubt that there are ways to make it much faster. But I think there are some possible improvements regarding robustness and bug-free-ness.

Your example file as a tab-delimited StringIO , to make testing a little easier:

from io import StringIO

data = StringIO("""\
Service Name,Port Number
pt-tls,271
pt-tls,271
Unassigned,272-279
http-mgmt,280
http-mgmt,280
personal-link,281
personal-link,281
cableport-ax,282
cableport-ax,282
rescap,283
rescap,283
corerjd,284
corerjd,284
Unassigned,285
fxp,286
fxp,286
k-block,287
k-block,287
Unassigned,288-307
novastorbakcup,308
novastorbakcup,308
""")

I wrote the loop as a generator instead of an aggregator, since it's a bit easier to work with in a setting where you have expanding ranges:

import csv

def extend_ports(file, delim=','):
   handle = csv.reader(file, delimiter=delim)
   yield next(handle)  # skip header
   for row in handle:
      try:
         service_name, port_number = row
      except ValueError:
          print(f"Could not parse line '{row}'")
          raise
      if '-' not in port_number:
         yield [service_name, port_number]  # simple result
      else:
         start, end = map(int, port_number.split('-'))
         for port in map(str, range(start, end+1)):
            yield [service_name, port]  # expanded result

# get the result
result = list(extend_ports(data))
# your call should be something like 
# result = list(extend_ports(open('my_config.csv')))

# print it
for line in result:
   print(line)

Which will print the desired format:

['Service Name', 'Port Number']
['pt-tls', '271']
['pt-tls', '271']
['Unassigned', '272']
['Unassigned', '273']
['Unassigned', '274']
['Unassigned', '275']
['Unassigned', '276']
['Unassigned', '277']
...
['Unassigned', '306']
['Unassigned', '307']
['novastorbakcup', '308']
['novastorbakcup', '308']

If you are satisfied with the result, you can write it back into a file using the same csv module that was used to read it:

with open('my_extended_config.csv', 'w') as f:
   writer = csv.writer(f, delimiter='\t')
   writer.writerows(result)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM