Что нового

Парсинг текстового файла с занесением данных в массив

cheslav

Новичок
Сообщения
18
Репутация
0
Версия AutoIt: 3.
v3.3.12.0
Описание:
Есть текстовый файл с объектами (в файле они под названием DFXA-n (где DFXA -имя , n - индекс))
Для каждого объекта в файле прописаны VLAN1, 2, 3 и т.д. с соответствующими IP адресами и маской /
Нумерация VLAN в файле 1,2,3,4,5,6,7 - в реальности может быть иной, но у всех объектов VLAN-ы всегда одинаковые

Хотелось бы распарсить и запихнуть в массив вида

индекс | имя | VLAN1 | VLAN2 | VLAN3 |.....| VLANn|
0 |DFXA| IP | IP | IP |.....| IP |
1 |DFXA| IP | IP | IP |.....| IP |

Маска в массиве не нужна (только IP)
Спасибо.
Примечания:
 

Вложения

  • print.txt
    5.4 КБ · Просмотры: 17

mef-t

Осваивающий
Сообщения
306
Репутация
30
Код:
#include <Array.au3>

$tText = FileRead ('print.txt')

$aMaxLan = StringRegExp ($tText, "VLAN(\d*)", 3)
$nMax = _ArrayMax($aMaxLan, 1)
$aCountDFXA = StringRegExp ($tText, "DFXA-(\d*)", 3)

Dim $aArray[UBound($aCountDFXA)][$nMax+2]
$DFXAindex = -1
ConsoleWrite (UBound($aCountDFXA) & ' ' & $nMax+2 & @CRLF)
$aText = StringRegExp ($tText, "(DFXA-\d+)|(VLAN\d+.*\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", 3)

For $i = 0 To UBound($aText)-1
   $aText[$i] = StringStripWS ($aText[$i], 7)

   $nDFXA = StringInStr ($aText[$i], "DFXA-")
   $nVLAN = StringInStr ($aText[$i], "VLAN")

   Select
	  Case $nDFXA > 0
		 $DFXAindex += 1
		 $aArray[$DFXAindex][0] = StringTrimLeft ($aText[$i], 5)
		 $aArray[$DFXAindex][1] = "DFXA"
	  Case $nVLAN > 0
		 $Space = StringInStr($aText[$i], " ", 1, $nVLAN)
		 $countForSpace = $Space - $nVLAN
		 $iVLAN = StringMid($aText[$i], $nDFXA + 5, $countForSpace-4) + 1
		 $result = StringTrimLeft ($aText[$i], StringInStr($aText[$i], " ", 0, -1))
		 ConsoleWrite ($DFXAindex & ' ' & $iVLAN & @CRLF)
		 $aArray[$DFXAindex][$iVLAN] = $result
	  EndSelect
Next

_ArrayDisplay($aArray)
 

Z_Lenar

Продвинутый
Сообщения
209
Репутация
52
Код:
#include <Array.au3>

Global $aRes = StringSplit(FileRead('print.txt'), 'DFXA-', 3)
Global $aDXFA[1], $maxDXFA = 0, $maxVLAN = 0, $aTmp[1]
For $i = 1 To UBound($aRes)-1
	$aTmp = StringRegExp($aRes[$i], 'VLAN(\d+).*?(\d+\.\d+\.\d+\.\d+)',3)
	If Not @error Then
		$maxDXFA += 1
		If $maxVLAN < UBound($aTmp)/2 Then $maxVLAN = UBound($aTmp)/2
		ReDim $aDXFA[$maxDXFA][$maxVLAN+1]
		$aDXFA[$maxDXFA-1][0] = 'DFXA-' & $i-1
		For $k = 1 To UBound($aTmp)/2
			$aDXFA[$maxDXFA-1][$aTmp[$k*2-2]] = $aTmp[$k*2-1]
		Next
	EndIf
Next
_ArrayDisplay($aDXFA)
 
Автор
C

cheslav

Новичок
Сообщения
18
Репутация
0
:scratch: оба варианта рабочие, но есть одна проблема: в случае наличия в файле объектов с другим именем к примеру DFXB не работают оба. Мой косяк надо было сразу предупредить про их возможное наличие. Ввиду того что они в результирующем массиве не нужны в первоначальный файл не включил. Прошу прощения. + в варианте Z_Lenar не парсится индекс объекта DFXA-n (n-индекс). Он должен быть в первом столбце.

DFXB-8
EL13 RP 1000
VLAN1 RP 1000 LIMC 10.0.1.10/32
->EL132 20 0/0
VLAN2 RP 1000 L 10.1.1.20/28
->EL13 3332 0/0
VLAN3 RP 1000 L 10.1.1.30/27
->EL13 3333 0/0
VLAN4 RP 1000 LM 10.1.1.40/28
->EL13 3335 0/0
VLAN5 RP 1000 LC 10.1.1.50/27
 

mef-t

Осваивающий
Сообщения
306
Репутация
30
Какой показатель является разделителем для разделов: пустая строка или имя без доп параметров.
Или какие имена возможны для разделов?


Добавлено:
Сообщение автоматически объединено:

Код:
#include <Array.au3>

$tText = FileRead ('print.txt')

$aMaxLan = StringRegExp ($tText, "VLAN(\d*)", 3)
$nMax = _ArrayMax($aMaxLan, 1)
$aCountDFXA = StringRegExp ($tText, "DFX.-(\d*)", 3)

Dim $aArray[UBound($aCountDFXA)][$nMax+2]
$DFXAindex = -1
$aText = StringRegExp ($tText, "(DFX.-\d+)|(VLAN\d+.*\d+\.\d+\.\d+\.\d+)", 3)

For $i = 0 To UBound($aText)-1
   $aText[$i] = StringStripWS ($aText[$i], 7)

   $nDFXA = StringInStr ($aText[$i], "DFX")
   $nVLAN = StringInStr ($aText[$i], "VLAN")

   Select
	  Case $nDFXA > 0
		 $DFXAindex += 1
		 $aArray[$DFXAindex][0] = StringTrimLeft ($aText[$i], 5)
		 $aArray[$DFXAindex][1] = StringLeft ($aText[$i], StringInStr($aText[$i], "-")-1)
	  Case $nVLAN > 0
		 $Space = StringInStr($aText[$i], " ", 1, $nVLAN)
		 $countForSpace = $Space - $nVLAN
		 $iVLAN = StringMid($aText[$i], $nVLAN + 4, $countForSpace-4) + 1
		 $result = StringTrimLeft ($aText[$i], StringInStr($aText[$i], " ", 0, -1))
		 $aArray[$DFXAindex][$iVLAN] = $result
	  EndSelect
Next

_ArrayDisplay($aArray)
 
Автор
C

cheslav

Новичок
Сообщения
18
Репутация
0
каждый раздел для определенного объекта начинается с его имени XXXX-n и заканчивается пустой строкой
имена могут быть разные
В 90% случаев это XXXX-n , где XXXX - латинские буквы и n-порядковый номер
также могут всречаться объекты XXX-n и просто XXXX или XXX без индекса в случае если объект присутствует в единственном экземпляре


Добавлено:
Сообщение автоматически объединено:

мне же из этого файла требуется вытянуть в массив данные только по конкретным объектам (в данном случае DFXA)


Добавлено:
Сообщение автоматически объединено:

примеры имен DFXA-n, DFXB-n, RDP, F:rofl:R-n, CPU-n
 

Z_Lenar

Продвинутый
Сообщения
209
Репутация
52
cheslav
Код:
#include <Array.au3>

Global $aRes = StringRegExp(FileRead('1.txt'), '(?s)(\w+-\d+)((?:.(?!\w+-))+)', 3)
Global $maxVLAN = 1, $aTmp[1]
Global $aDXFA[UBound($aRes)/2][1]
For $i = 0 To UBound($aRes) - 2 Step 2
    $aTmp = StringRegExp($aRes[$i+1], 'VLAN(\d+).*?(\d+\.\d+\.\d+\.\d+)',3)

	$aDXFA[$i/2][0] = $aRes[$i]
    If Not @error Then
        If $maxVLAN < UBound($aTmp)/2 Then
			$maxVLAN = UBound($aTmp)/2
			ReDim $aDXFA[UBound($aRes)/2][$maxVLAN + 1]
		EndIf
        For $j = 0 To UBound($aTmp)/2 - 1
            $aDXFA[$i/2][$aTmp[$j * 2]] = $aTmp[$j * 2 + 1]
        Next
    EndIf
Next
_ArrayDisplay($aDXFA)
Так сойдет?
 

mef-t

Осваивающий
Сообщения
306
Репутация
30
Полагаю, тут так же остается пропущенным раздел с именем XXXX или XXX без индекса


Добавлено:
Сообщение автоматически объединено:

мне же из этого файла требуется вытянуть в массив данные только по конкретным объектам (в данном случае DFXA)
А вот этого не понял.
Т.е. нужно все таки именно "DFXA" или же "DFXA-n, DFXB-n, RDP, F:rofl:R-n, CPU-n"?


Добавлено:
Сообщение автоматически объединено:

Или же не правильно отрабатывает с наличием других имен?
Тогда так:
Код:
#include <Array.au3>

$tText = FileRead ('print.txt')
Dim $aArray[UBound(StringRegExp ($tText, "DFXA-(\d*)", 3))][_ArrayMax(StringRegExp ($tText, "VLAN(\d*)", 3), 1)+2]
$aText = StringRegExp ($tText, "DFX.-\d+|VLAN\d+|\d+\.\d+\.\d+\.\d+", 3)
$DFXAindex = -1
$skip = False
For $i = 0 To UBound($aText)-1
   If StringInStr($aText[$i], "DFXA-") = 0 And StringInStr($aText[$i], "VLAN") = 0 And StringInStr($aText[$i], ".") = 0 Then
	  $skip = True
   EndIf
   If StringInStr($aText[$i], "DFXA-") > 0 Then
	  $skip = False
	  $DFXAindex += 1
	  $aArray[$DFXAindex][0] = StringTrimLeft ($aText[$i], 5)
	  $aArray[$DFXAindex][1] = StringLeft ($aText[$i], StringInStr($aText[$i], "-")-1)
   ElseIf Not $skip Then
	  $nVLAN = StringInStr ($aText[$i], "VLAN")
	  If $nVLAN > 0 Then
		 $iVLAN = StringMid($aText[$i], $nVLAN + 4, StringInStr($aText[$i], " ", 1, $nVLAN) - $nVLAN - 4) + 1
	  Else
		 $aArray[$DFXAindex][$iVLAN] = $aText[$i]
	  EndIf
   EndIf
Next
_ArrayDisplay($aArray)
 
Автор
C

cheslav

Новичок
Сообщения
18
Репутация
0
нужно только DFXA. Это я привел пример как еще могут называться объекты в одном и том же файле


Добавлено:
Сообщение автоматически объединено:

в массив должны попасть данные только по объектам DFXA независимо от того есть в файле другие объекты или нет.
 

Z_Lenar

Продвинутый
Сообщения
209
Репутация
52
mef-t [?]
Полагаю, тут так же остается пропущенным раздел с именем XXXX или XXX без индекса
Ну конечно можно разбить по разделителю двойного @CRLF. А потом первую строку выдавать как идентификатор раздела. И потом все содержимое построчно парсить. А в случае ошибки во входном файле выдавать MsgBox с последующим Exit, Shutdown и в самом конце, перед отключением питания, BSOD. :laugh:
Но задача была дана проще и откуда смысл копать дальше?


Добавлено:
Сообщение автоматически объединено:

Вариант:
Код:
#include <Array.au3>

$aLines = StringSplit(FileRead('1.txt'), @CRLF, 3)
$bNextGroup = True
Global $aGroups[1][1], $nGroups = 1, $nVLANs = 0, $bIPFound = False
For $i = 0 To UBound($aLines) - 1
	If $bNextGroup And StringRegExp($aLines[$i], '^(DFX\w+-?\d*)\s*$') Then
		If $bIPFound Then
			$nGroups += 1
			ReDim $aGroups[$nGroups][$nVLANs + 1]
		EndIf
		$aGroups[$nGroups-1][0] = StringRegExpReplace($aLines[$i], '[^\w-]', '')
		$bNextGroup = False
		$bIPFound = False
	ElseIf StringRegExp($aLines[$i], '^\s*$') Then
		$bNextGroup = True
	EndIf

	$aTmp = StringRegExp($aLines[$i], 'VLAN(\d+).*(\d+\.\d+\.\d+\.\d+)', 1)
	If Not @error Then
		If $aTmp[0] > $nVLANs Then
			$nVLANs = $aTmp[0]
			ReDim $aGroups[$nGroups][$nVLANs + 1]
		EndIf
		$aGroups[UBound($aGroups, 1)-1][$aTmp[0]] = $aTmp[1]
		$bIPFound = True
	EndIf
Next
_ArrayDisplay($aGroups)
 
Автор
C

cheslav

Новичок
Сообщения
18
Репутация
0
вот файл с несколькими объектами под разными именами. Все остальное стандартно:
массив в формате из первого поста. Заполнение - объекты F:rofl:A и ip адреса для их VLAN. Все остальные обекты с их адресами и vlanами не нужны.

P.S. Можно конечно распарсить и все и потом отсортировав по имени раскидать по разным массивам - это уж я не знаю как проще.
 

Вложения

  • print.txt
    7.8 КБ · Просмотры: 6

Z_Lenar

Продвинутый
Сообщения
209
Репутация
52
cheslav
Код:
#include <Array.au3>

$aLines = StringSplit(FileRead('print.txt'), @CRLF, 3)
Global $aGroups[0][0], $nGroups = 0, $nVLANs = 0, $bIPFound = True, $bNextGroup = True
For $i = 0 To UBound($aLines) - 1
    If $bNextGroup And StringRegExp($aLines[$i], '^(DFX\w+-?\d*)\s*$') Then
        If $bIPFound Then
            $nGroups += 1
            ReDim $aGroups[$nGroups][$nVLANs + 1]
        EndIf
        $aGroups[$nGroups-1][0] = StringRegExpReplace($aLines[$i], '[^\w-]', '')
        $bNextGroup = False
        $bIPFound = False
    ElseIf StringRegExp($aLines[$i], '^\s*$') Then
        $bNextGroup = True
    EndIf

    $aTmp = StringRegExp($aLines[$i], 'VLAN(\d+).*(\d+\.\d+\.\d+\.\d+)', 1)
    If Not @error And Not $bNextGroup Then
        If $aTmp[0] > $nVLANs Then
            $nVLANs = Number($aTmp[0])
            ReDim $aGroups[$nGroups][$nVLANs + 1]
        EndIf
        $aGroups[UBound($aGroups)-1][$aTmp[0]] = $aTmp[1]
        $bIPFound = True
    EndIf
Next
_ArrayDisplay($aGroups)
 
Автор
C

cheslav

Новичок
Сообщения
18
Репутация
0
Z_Lenar почти то что надо, только в массив ip адреса попадают без первого символа ( и индекс элемента DFXA по прежнему не парсится (я имею ввиду что если это к примеру DFXA-1, то в первом столбце массива должно быть 1, во втором "DFXA" (просто без тире и индекса)) ну а дальше уже ip. И данный парсер умеет обрабатывать VLAN от 1до 9 к примеру строка VLAN10 вызовет проблемы


Добавлено:
Сообщение автоматически объединено:

VLANs для элемента может меняться в диаппазоне от VLAN0 до VLAN4095
 

Z_Lenar

Продвинутый
Сообщения
209
Репутация
52
Вроде все.
Код:
#include <Array.au3>

$aBlocks = StringSplit(FileRead('1.txt'), @CRLF & @CRLF, 3)
Global $aGroups[1][1], $nGroups = 0, $nVLANs = 0
For $i = 0 To UBound($aBlocks) - 1
	$aTmp = StringRegExp($aBlocks[$i], '^\s*DFXA-(\d+)', 1)
	If @error Then ContinueLoop
	If StringRegExp($aBlocks[$i], '(?m)^\s*VLAN\d+.*?\d+\.\d+\.\d+\.\d+') = 0 Then ContinueLoop
	$nGroups += 1
	ReDim $aGroups[$nGroups][$nVLANs+2]
	$aGroups[$nGroups-1][0] = $aTmp[0]
	$aGroups[$nGroups-1][1] = 'DFXA'
	$aTmp = StringRegExp($aBlocks[$i], '(?m)^\s*VLAN(\d+).*?(\d+\.\d+\.\d+\.\d+)', 3)
	For $j = 0 To UBound($aTmp) / 2 - 1
		If $nVLANs < $aTmp[$j*2] Then
			$nVLANs = Number($aTmp[$j*2])
			ReDim $aGroups[$nGroups][$nVLANs+2]
		EndIf
		$aGroups[$nGroups-1][$aTmp[$j*2]+1] = $aTmp[$j*2+1]
	Next
Next
_ArrayDisplay($aGroups)
Моя вина не внимательно делал. (Странно пиво пить только собирался... ;))
 
Автор
C

cheslav

Новичок
Сообщения
18
Репутация
0
да почти. Только по прежнему проблема если VLAN>9 к примеру если у объекта есть VLAN10 или VLAN4095 то все криво


Добавлено:
Сообщение автоматически объединено:

если будет адекватно воспринимать любой VLAN от 0 до 4095 тогда точно всё. :smile:



Добавлено:
Сообщение автоматически объединено:

Что-то типа такого я имею ввиду
DFXA-3
EL132 RP 1000
EL13 RP 1000
VLAN1 RP 1000 LIMC 10.0.1.11/25
->EL132 20 0/0
VLAN25 RP 1000 L 10.1.1.12/28
->EL13 3332 0/0
VLAN36 RP 1000 L 10.1.1.13/28
->EL13 3333 0/0
VLAN471 RP 1000
->EL13 3335 0/0
VLAN59 RP 1000 LC 10.1.1.14/28
->EL13 3336 0/0
VLAN4094 RP 1000 L 10.1.1.15/28
ERTX
->EL13 3344 0/0
VLAN3000 RP 1000 L 10.1.1.16/28
ERTZ
->EL13 3345 0/0
 

Z_Lenar

Продвинутый
Сообщения
209
Репутация
52
cheslav
Вообще-то у меня VLAN > 9 правильно воспринимает. Функция _ArrayDisplay() ограничивает показ 250 столбцами. Может еще и разница версий AutoIt. У меня в 3.3.12 пример с VLAN4094 работает.


Добавлено:
Сообщение автоматически объединено:

cheslav [?]
В первом же сообщении было указано начало с VLAN1?


Добавлено:
Сообщение автоматически объединено:

Если все-же надо с нуля, нужно будет в предыдущем сообщении исправить:
Код:
ReDim $aGroups[$nGroups][$nVLANs+3]
		EndIf
		$aGroups[$nGroups-1][$aTmp[$j*2]+2] = $aTmp[$j*2+1]
 

mef-t

Осваивающий
Сообщения
306
Репутация
30
Мой вариант:
Код:
#include <Array.au3>
$tText = FileRead ('print.txt')
$CountArr = UBound(StringRegExp ($tText, "DFXA-(\d*)", 3))
Dim $aArray[$CountArr][3]
$maxVlan = 3
$aText = StringRegExp ($tText, "(?m)(^[A-Z]+-?\d*?)\h*$|VLAN\d+|\d+\.\d+\.\d+\.\d+", 3)
$DFXAindex = -1
$skip = True
For $i = 0 To UBound($aText)-1
   If StringInStr($aText[$i], "DFXA-") = 0 And StringInStr($aText[$i], "VLAN") = 0 And StringInStr($aText[$i], ".") = 0 Then
	  $skip = True
   EndIf
   If StringInStr($aText[$i], "DFXA-") > 0 Then
	  $skip = False
	  $DFXAindex += 1
	  $aArray[$DFXAindex][0] = StringTrimLeft ($aText[$i], 5)
	  $aArray[$DFXAindex][1] = StringLeft ($aText[$i], StringInStr($aText[$i], "-")-1)
   ElseIf Not $skip Then
	  $nVLAN = StringInStr ($aText[$i], "VLAN")
	  If $nVLAN > 0 Then
		 $iVLAN = StringMid($aText[$i], $nVLAN + 4, StringInStr($aText[$i], " ", 1, $nVLAN) - $nVLAN - 4) + 1
	  Else
		 If ($maxVlan < $iVLAN + 1) Then
			ReDim $aArray[$CountArr][$iVLAN + 1]
		 EndIf
		 $aArray[$DFXAindex][$iVLAN] = $aText[$i]
	  EndIf
   EndIf
Next
_ArrayDisplay($aArray)

Z_Lenar правильно говорит, _ArrayDisplay() не отображает больше 250 полей, но это не значит, что их нет.
Вы можете проверить наличие значений, выведя их через консоль или msgBox
 
Автор
C

cheslav

Новичок
Сообщения
18
Репутация
0
вобщем да работает. Это я тут у себя слегка накосячил. Всем спасибо огромное. :smile:
 
Верх