TextFSM: Análise de Texto Semiestruturado com Máquinas de Estado

Introdução

TextFSM é um módulo Python que utiliza um motor de máquina de estados finitos (FSM) com base em templates para analisar texto semiestruturado. Originalmente concebido para extrair dados de saídas de linhas de comando (CLI) de dispositivos de rede, como roteadores e switches, sua aplicação pode ser estendida a qualquer tipo de saída textual que siga um padrão. O sistema requer dois elementos principais: um arquivo de template e os dados textuais de entrada (por exemplo, a saída de um comando CLI). Como resultado, ele retorna uma estrutura tabular contendo os dados extraídos.

É importante notar que cada estrutura de texto distinta requer seu próprio arquivo de template. A comunidade é encorajada a desenvolver e compartilhar templates para diversas fontes de dados. A criação de um repositório de templates permite que scripts chamem o TextFSM para extrair informações úteis de várias fontes, possibilitando também a geração de diferentes visualizações tabulares a partir dos mesmos dados, utilizando templates distintos.

Funcionamento Detalhado

Utilizando a Biblioteca

Um exemplo rápido de como usar a biblioteca:


import textfsm

# Carrega o template e os dados brutos
with open("meu_template.textfsm", "r") as template_file:
   raw_cli_output = "..." # Sua string de saída CLI aqui
   
   # Cria a instância do TextFSM
   fsm_parser = textfsm.TextFSM(template_file)
   
   # Analisa o texto
   parsed_data = fsm_parser.ParseText(raw_cli_output)

# Exibe os resultados em formato CSV
print( ', '.join(fsm_parser.header) )
for row in parsed_data:
   print( ', '.join(row) )
 

A biblioteca também pode ser executada diretamente pela linha de comando para validar a sintaxe do template e comparar a saída esperada com a entrada:


python -m textfsm.parser [--help] <template_file> [input_file] [output_file]
 </template_file>

Se o TextFSM for instalado como um pacote, o executável parser.py estará localizado no diretório de pacotes do Python correspondente à sua versão.

Estrutura dos Dados Extraídos

O objetivo principle do FSM é extrair dados cruciais de entradas de texto e organizá-los em um formato tabular. Considere a seguinte entrada de dados brutos, onde o interesse reside no estado e na temperatura das unidades de processamento:


Routing Engine status:
 Slot 0:
   Current state                  Master
   Election priority              Master (default)
   Temperature                 39 degrees C / 102 degrees F
   CPU temperature             55 degrees C / 131 degrees F
   DRAM                      2048 MB
   Memory utilization          76 percent
   CPU utilization:
     User                      95 percent
     Background                 0 percent
     Kernel                     4 percent
     Interrupt                  1 percent
     Idle                       0 percent
   Model                          RE-4.0
   Serial ID                      xxxxxxxxxxxx
   Start time                     2008-04-10 20:32:25 PDT
   Uptime                         180 days, 22 hours, 45 minutes, 20 seconds
   Load averages:                 1 minute   5 minute  15 minute
                                      0.96       1.03       1.03
Routing Engine status:
 Slot 1:
   Current state                  Backup
   Election priority              Backup
   Temperature                 30 degrees C / 86 degrees F
   CPU temperature             31 degrees C / 87 degrees F
   DRAM                      2048 MB
   Memory utilization          14 percent
   CPU utilization:
     User                       0 percent
     Background                 0 percent
     Kernel                     0 percent
     Interrupt                  1 percent
     Idle                      99 percent
   Model                          RE-4.0
   Serial ID                      xxxxxxxxxxxx
   Start time                     2008-01-22 07:32:10 PST
   Uptime                         260 days, 10 hours, 45 minutes, 39 seconds
 

Aplicando um template apropriado ao TextFSM para processar essa entrada, o resultado é uma tabela onde os slots e seus dados associados são organizados em campos:

Slot Modelo DRAM Estado Temperatura TempCPU
0 RE-4.0 2048 Master 39 55
1 RE-4.0 2048 Backup 30 31

Arquivos de Template

Um arquivo de template define como o FSM deve procesasr os dados de entrada. Diferentes formatos de texto exigem templates específicos; por exemplo, a saída de comandos de roteador geralmente necessita de um template dedicado para cada comando.

Abaixo está um exemplo completo de template, demonstrando como processar a saída do comando 'show chassis routing-engine' em um roteador:


# Template para 'show chassis routing-engine'
Value Filldown Chassis (.cc.?-re.)
Value Required Slot (\d+)
Value State (\w+)
Value Temp (\d+)
Value CPUTemp (\d+)
Value DRAM (\d+)
Value Model (\S+)

Start
 ^${Chassis}
 ^Routing Engine status: -> Record RESlot

RESlot
 ^\s+Slot\s+${Slot}
 ^\s+Current state\s+${State}
 ^\s+Temperature\s+${Temp} degrees
 ^\s+CPU temperature\s+${CPUTemp} degrees
 ^\s+DRAM\s+${DRAM} MB
 ^\s+Model\s+${Model} -> Start
 

Um arquivo de template é composto por duas seções principais:

  • Definições de Valor (Value): Descrevem as colunas de dados a serem extraídas, que aparecerão na tabela resultante. Todas as definições de Value devem preceder as definições de estado e ser adjacentes (exceto quando separadas por comentários).
  • Definições de Estado (State): Uma ou mais seções que descrevem os diferentes estados da máquina de estados durante o processo de análise.

Linhas que começam com um caractere '#' (possivelmente precedido por espaços em branco) são consideradas comentários.

Definições de Valor (Value)

Cada linha de definição de Value segue o formato:

Value [opção[,opção...]] nome regex
Palavra-chave Tipo Descrição
Value Obrigatório Inicia a definição de um valor.
opção Flags (separadas por vírgula, sem espaços) - Filldown: Mantém o valor anterior para registros subsequentes, a menos que seja explicitamente alterado ou correspondido novamente. - Key: Declara que o conteúdo deste campo é um identificador único para a linha. - Required: A linha só será salva na tabela se este valor corresponder. - List: Indica que o valor é uma lista, acumulando correspondências em vez de sobrescrever. - Fillup: Similar a Filldown, mas preenche para cima até encontrar um registro não vazio. Incompatível com Required ou List.
nome Nome do campo Nome usado para o valor, que se tornará o nome da coluna na tabela final. Não pode conflitar com nomes de opções.
regex Expressão regular Uma expressão regular entre parênteses, usada para capturar o valor.

Definições de Estado

Após as definições de Value, seguem as definições de estado. Cada definição de estado é separada por uma linha em branco. A primeira linha é o nome do estado (alfanumérico), seguida por uma série de regras.

O formato de uma definição de estado completa é:

NomeDoEstado
  ^regra1
  ^regra2
  ...

As regras dentro de um estado devem ser contíguas (sem linhas em branco) e precedidas por um ou dois espaços seguidos pelo caractere '^'.

O FSM inicia no estado Start. Uma linha de entrada só é comparada com as regras do estado atual. Uma correspondência pode acionar uma transição para um novo estado. O processamento linha a linha continua até que o estado EOF seja alcançado ou uma transição para o estado End ocorra.

Estados Reservados

O estado Start é obrigatório para iniciar o processamento. O estado EOF (End Of File) é um estado implícito que é executado quando o final da entrada é atingido. Ele normalmente executa um comando Record antes de retornar.

É possível sobrescrever o comportamento padrão do EOF definindo-o explicitamente:

EOF
   ^.* -> Record

Ou, para evitar qualquer ação:

EOF

O estado End é um estado reservado que encerra o processamento da entrada sem executar o estado EOF.

Regras de Estado

Cada definição de estado consiste em uma ou mais regras. O FSM lê uma linha da entrada e a compara sequencialmente com as regras do estado atual. Se uma regra corresponder, sua ação associada é executada, e o processo recomeça (geralmente a partir do estado Start ou do estado para o qual a transição foi definida).

O formato de uma regra é:

^regex [-> ação]

regex é uma expressão regular que deve corresponder ao início da linha de entrada. O caractere '^' é implicitamente adicionado.

A expressão regular pode conter descritores de valor no formato $ValorNome ou ${ValorNome} (preferencial). Ao encontrar uma correspondência, o texto capturado pelo regex associado ao valor é atribuído ao registro.

O final de uma linha pode ser marcado com $$, que será substituído por '$' durante a substituição do valor.

Exemplo:


Value Interface (\S+)

Start
 ^Interface ${Interface} is up
 

A regra acima se expandirá para:

^Interface (\S+) is up

Se a linha de entrada for "Interface GigabitEthernet1/10 is up.", o valor "GigabitEthernet1/10" será atribuído à variável Interface.

Múltiplos descritores de valor podem ser usados em uma única regra, exigindo que todas as correspondências adicionais sejam bem-sucedidas para que todos os valores sejam atribuídos.

Ações de Regra

Após a expressão regular, uma ação pode ser especificada, separada por ->. As ações são compostas por três partes opcionais: A) Ação de Linha, B) Ação de Registro, e C) Transição de Estado.

Se nenhuma ação for especificada (sem ->), a ação implícita padrão é Next.NoRecord.

Ações de Linha

Ação Descrição
Next Processa a próxima linha de entrada, reiniciando a correspondência do estado atual. É a ação padrão se nenhuma ação de linha for especificada.
Continue Mantém a linha atual e continua o processamento das regras no estado atual, como se a correspondência não tivesse ocorrido (a atribuição de valores ainda acontece). Comportamento de Continue não aceita transição de estado.

Ações de Registro

Ocorrem após a ação de linha, separadas por um ponto (.).

Ação Descrição
NoRecord Nenhuma ação de registro. É o padrão se nenhuma ação de registro for especificada.
Record Adiciona os valores coletados até o momento como uma nova linha na tabela de resultados. Valores não Filldown são limpos. Se algum valor Required não foi atribuído, a linha não será adicionada.
Clear Limpa os valores que não são Filldown.
Clearall Limpa todos os valores.

O ponto (.) é necessário apenas quando tanto a ação de linha quanto a de registro são explicitamente especificadas. Se uma ou ambas forem padrão, o ponto pode ser omitido.

Transição de Estado

Opcionalmente, um novo nome de estado pode ser especificado após as ações de linha ou registro, separado por um espaço. Isso indica uma transição para o novo estado. O novo estado deve ser válido e definido no template.

Após a execução das ações, uma nova linha é lida da entrada, o estado atual é alterado para o novo estado, e o processamento continua a partir daí.

Ação de Erro

A ação especial Error encerra todo o processamento, descarta os dados coletados até o momento e lança uma exceção. Pode incluir uma mensagem opcional.

^regex -> Error [palavra|"string"]

Tags: textfsm Python CLI parsing Regex

Publicado em 6-30 23:31