How to extract data from a single column list and generate another?

Asked

Viewed 120 times

0

Good morning. I’m new to programming and I started out with curiosity and the need to eliminate some repetitive functions from my day to day.

I am creating a code that enters a network equipment (netmiko library), gives a command and picks up the return of it. The output is something similar to the one shown below, always comes 1 line with 'Underlying Interface: ' and another with 'Stacked VLAN Id: 0x8100.'.

1 - What I tried and am not getting is to delete these words leaving only 'Xe-1/0/6' and '2847' for all lines. When I ran two separate if, I was able to delete the words leaving only what I want, but only for the first appearance.

I tried to do it with a go, but I can’t get an answer.

2 - After I can do step 1, I need to organize the data in column 1 (all appearances that have Xe - odd lines) and column 2 ( all appearances that have the last 4 numbers ex:2847 - even lines)

output returns that list that can have 500 lines or up to 120 thousand:
output=
Underlying Interface: Xe-1/0/6
Stacked VLAN Id: 0x8100.2847
Underlying Interface: Xe-1/0/7
Stacked VLAN Id: 0x8100.2842
Underlying Interface: Xe-1/0/9
Stacked VLAN Id: 0x8100.2862

output = connection.send_command(command)

for p in range(0, len(output), 1):
     if '0x8100.' in output[p]:
         vlan = output[p]
         vlan = vlan[vlan.find('0x8100')+7:vlan.find('0x8100')+11]
         print(vlan)

     if 'Interface' in output[p]:
        interface = output[p]
        interface = interface[interface.find('Interface') + 11:interface.find('Interface') + 19]
        print(interface)

final result I am seeking:
Xe-1/0/6 2847
Xe-1/0/7 2842
Xe-1/0/9 2862


Edit 1: The answer brings only the first appearance: ['Xe-1/0/6'], ['2847']] The ouput data is obtained from the response of a network equipment, so I forced them into a string and put them in a list. Below follows the code just hiding the data from the equipment and password.
Complete output list: https://drive.google.com/open?id=12qq5P0DqFWheCDuNW6wTP4M7qkjT1HtV

import netmiko
import time

start = time.time()

connection = netmiko.ConnectHandler(ip='100.100.100.100',device_type='juniper_junos',username='teste',password='teste')
command = 'show subscribers client-type vlan detail | match "^Underlying Interface\:|^Stacked VLAN Id"'

outputA = connection.send_command(command)
outputB = str(outputA)
output = [outputA]

connection.disconnect()

result = [[], []]
for p in range(len(output)):
    if '0x8100.' in output[p]:
        result[1].append(output[p][output[p].find('0x8100')+ 7 : output[p].find('0x8100') + 11])
    if 'Interface' in output[p]:
        result[0].append(output[p][output[p].find('Interface') + 11 : output[p].find('Interface') + 19])

print(result)

end = time.time()
print('Tempo de execução: {} segundos'.format((end - start)))

Python response: ['Xe-1/0/6'], ['2847']]
Running time: 6.372122049331665 seconds


Edit 2 - print showing outputA class and outputA print inserir a descrição da imagem aqui

2 answers

1


I managed to get to that code for your problem:

result = [[], []]
for p in range(len(output)):
    if '0x8100.' in output[p]:
        result[1].append(output[p][output[p].find('0x8100')+ 7 : output[p].find('0x8100') + 11])
    if 'Interface' in output[p]:
        result[0].append(output[p][output[p].find('Interface') + 11 : output[p].find('Interface') + 19])

print(result)
  1. You were assigning the string "clean" always to the same variable, so at each iteration you erased the old value and put a new one in place. So to store all the values, you should put this in a list. The method append() list, add the value you pass to it at the end of the list.
  2. Since you need two "columns", from to use a list that contains 2 other lists inside, one for column 1 and the other for column 2. To access a value, you use for example: result[0][0], ( value of first row and first column).

EDIT 1:

Whereas the return of the function connection is a huge string, so you need to break it into a list, for the method I suggested to work. I believe you can do it this way:

outputA = connection.send_command(command)
output = outputA.split('\n')

Using the method split in the outputA, with the separator parameter \n, you break the string in the "line breaks", returning you a list with each line. Then you can pass the output for the code I indicated. I hope it works this time.

  • First thank you. I tried here and it hasn’t worked yet, but I will study step by step what you said and keep trying. Already gave me a huge north, mainly about the fact of cleaning the variable in the for.

  • For this code, I assumed that the output variable is from the list class, and it contains strings, according to the data you entered, can you please confirm this? And what error occurred this time?

  • Leonardo, I did Edit 1 in the text with the details and with the full code, full output too. Thanks again.

  • Look, here I can’t run this part of netmiko, but I noticed that its variable output gets outputA, instead of outputB, which would be the string, besides I’m not completely sure about this "conversion" to list, you should use the function list(outputB). Do the following, read the data from netmiko in the outputA variable, and use print(type(outputA)), and tell me what type of this variable.

  • the output class of it is a list, it declares when it converts the outputA, the problem is that it did not pass the outputA elements by a loop and then popular a list ai wanted to know if the conversion was not defective, if it was not just take the output and pass as parameter to my function that already solves the problem

  • On your test Leonardo, the return: <class 'str'> I’m understanding the Jefferson code now.

  • So the Connection function is returning a string? You need to break this string into a list, so you can move on to the separation functions. Please update your question, put a screenshot of print(outputA). For from the format of this string, we try to break it in the list you need.

  • Leonardo did Edit 2 with Print. The code provided by Jeferson for a generic output is not bringing feedback, I’m still understanding and testing some things to try to adjust (it will take a little time).

  • I will do an Edit in my answer, I think I understand the problem. Is that your return is a single string, with several lines.

  • Leonardo, everything worked out. I already created a dataframe with the two columns and I will work on them. Thank you so much for your support. I just can’t get a vote on the answers yet for lack of reputation, but as soon as I do, I’ll give you the feedback. Now I will study the codes of the two of you to better understand the step by step.

  • Top, any questions can call here.

Show 6 more comments

0

Hello, first of all welcome.

I would advise that the next time you ask a question leave all the source code you are using because it would be better to assist knowing fully what it is, I will try to help the way I can with the information you have given us.

You will need to make an important change to your code, try to run the code below from your original code the first one posted with these modifications.

output = connection.send_command(command)

listaObjetos = []

for i in output:
    listaObjetos.append(i)

def categorizar(outputList):
    UnderlyingList = []
    StackedList = []
    joinList = []
    for Under in outputList:
        if 'Underlying' in Under:
            UnderlyingList.append(Under.replace('Underlying Interface: ', ''))
        else:
            pass
    for Stacked in outputList:
        if 'Stacked' in Stacked:
            StackedList.append(Stacked.replace('Stacked VLAN Id: 0x8100.', ''))
        else:
            pass
    for count in range(len(UnderlyingList)):
        joinList.append('{} {}'.format(UnderlyingList[count], StackedList[count]))
    return joinList

for item in categorizar(listaObjetos):
    print(item)

As I do not have access to the original output I did a simulation but you should take the output and add each item directly to a list WITHOUT PROCESSING ANYTHING.

I tested the code by simulating its output in list form and it worked:


output = ['Underlying Interface: xe-1/0/6', 'Stacked VLAN Id: 0x8100.2847', 
            'Underlying Interface: xe-1/0/7', 'Stacked VLAN Id: 0x8100.2842', 
            'Underlying Interface: xe-1/0/9', 'Stacked VLAN Id: 0x8100.2862']

def categorizar(outputList):
    UnderlyingList = []
    StackedList = []
    joinList = []
    for Under in outputList:
        if 'Underlying' in Under:
            UnderlyingList.append(Under.replace('Underlying Interface: ', ''))
        else:
            pass
    for Stacked in outputList:
        if 'Stacked' in Stacked:
            StackedList.append(Stacked.replace('Stacked VLAN Id: 0x8100.', ''))
        else:
            pass
    for count in range(len(UnderlyingList)):
        joinList.append('{} {}'.format(UnderlyingList[count], StackedList[count]))
    return joinList

for item in categorizar(output):
    print(item)

my output was:

xe-1/0/6 2847
xe-1/0/7 2842
xe-1/0/9 2862
  • Jefferson, good afternoon. Thank you for your support. I even made an Edit (Edit 1) about 40 minutes ago exposing all the code and the complete list of output (I was playing a little late). I will study the code to understand step by step what passed and test the code, as soon as I get news return here.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.