如何获取两个数字之间的值,该数字是字符串并在python中用“-”符号分隔?

时间:2019-08-06 06:41:25

标签: python python-3.x

所以,我要解决的问题是将所有端口号从0到65535进行分类。我得到的材料几乎可以解决问题。 我有一个csv文件(逗号分隔),其中有两列,其中一列是端口号,另一列是其服务名称(分类)。在端口号的某些列中,我有一个范围,即“ 100-200”,它是一个字符串。

例如:-

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

现在原始2和11中有一个范围。即272至279和288至307。
如何将其转换为端口号并映射到相同的服务名称。 结果应该看起来像。

服务名称端口号

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

我尝试过

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)

上面的代码需要很多时间。 有什么优雅的方法可以解决这个问题。

如果有任何材料已经映射了端口,请在您的答案中加上

1 个答案:

答案 0 :(得分:1)

考虑到您已经编写的代码,我怀疑是否存在使它更快的方法。但是我认为在健壮性和无错误性方面有一些可能的改进。

您的示例文件以制表符分隔的StringIO形式,使测试更加容易:

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
""")

我将循环写为生成器而不是聚合器,因为在具有扩展范围的设置中使用它要容易一些:

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)

将打印所需的格式:

['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']

如果对结果感到满意,则可以使用与读取结果相同的csv模块将其写回到文件中:

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