Что нового

csv-файл в массив с помощью регулярного выражения

ildar

Осваивающий
Сообщения
252
Репутация
29
Есть csv-файл, вот кусок содержимого:
Код:
CO-DIANA,co-vm02.co.essen,"DIGITAL ANALYTICS PRO – аналитическая OLAP-система",PoweredOn,2,4,170, 172.16.10.173,,VM02_store0
CO-DIRECTUM,co-vm05.co.essen,"co-directum - тестовый",PoweredOn,4,24,190, 172.16.10.96,Гилазов Фанис,SinelogyB_02 VM-SAN4
CO-DIRECTUM01,co-vm06.co.essen,"co-directum01 - рабочий",PoweredOn,8,12,290, 172.16.10.97,Гилазов Фанис,SinelogyB_02 VM-SAN4
CO-DIRECTUM-CA,co-vm07.co.essen,"Образ Windows 2012 для серверов VB, DC, Service",PoweredOn,2,4,40, 172.16.10.102,Гилазов Фанис,Database 1 (RAID 10)
CO-DM_Storage,co-vm05.co.essen,"Голова для хранилища ДМ",PoweredOn,4,8,3824, 172.16.10.75,Нестерова Наталья,VM-SAN1 VM-SAN4 DM_Storage-2(Synology814)
CO-EDO-OPTOVIK,co-vm08.co.essen,"Этлас",PoweredOn,2,4,100, 172.16.10.131,Чернов Андрей,SinelogyB_01
надеялся с помощью такого кода
Код:
$j = 0
		While 1
			$sLine = FileReadLine($File)
			If @error = -1 Then ExitLoop			
			$aArrayLine	= StringSplit($sLine, ',')			
			For $i = 1 to UBound($aArrayLine) - 1
				$aArrayOUT[$j][$i - 1] = $aArrayLine[$i]
			Next
			$j += 1			
		WEnd
Разделяя строки через разделитель (запятая), но оказалось что текст содержит подобные строки
Код:
CO-DIRECTUM-CA,co-vm07.co.essen,"Образ Windows 2012 для серверов VB, DC, Service",PoweredOn,2,4,40, 172.16.10.102,Гилазов Фанис,Database 1 (RAID 10)
где кусок "Образ Windows 2012 для серверов VB, DC, Service" сбивает весь порядок. Думаю можно занести текст в массив с помощью регулярного выражения, но ничего в голову не приходит. Какую я вижу тут закономерность? Часть текста в которой не нужно рассматривать запятые в качестве разделителя, выделена в кавычки. В других местах файла (файл большой), кавычки не используются. на примере этой строки что должно получится:
Код:
$aArrayLine = ('CO-DIRECTUM-CA', 'co-vm07.co.essen', '"Образ Windows 2012 для серверов VB, DC, Service"', 'PoweredOn', '2', '4', '40', '172.16.10.102', 'Гилазов Фанис', 'Database 1 (RAID 10)')
С регулярными выражениями работал, но эта задача мне оказалась не под силу. Надеюсь на Вашу помощь.
Спасибо!
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Код:
Dim  $aArrayOUT[6][10]
$File = FileOpen("test.txt")
$j = 0
$pattern = '(?(?=")(".*?")|[^,]+)'
        While 1
            $sLine = FileReadLine($File)
            If @error = -1 Then ExitLoop    
            $aArrayLine = StringRegExp($sLine, $pattern, 3)         
            For $i = 0 to UBound($aArrayLine) - 1
                $aArrayOUT[$j][$i] = $aArrayLine[$i]
            Next
            $j += 1         
        WEnd
FileClose($File)

_ArrayDisplay($aArrayOUT)
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
Код:
StringRegExp($file,'(?m)(?<=^|,)(?:"[^"\r\n]*+"|[^,"\r\n])*+',3)
 
Автор
ildar

ildar

Осваивающий
Сообщения
252
Репутация
29
edyapd
Хорошее решение, но после обработки всего файла я увидел в содержимом пустые места, то есть две запятых подряд. Например:
Код:
CO-ATS,192.168.200.56,"Asterisk",PoweredOn,1,4,140, 192.168.10.137,,001
Ваш вариант их пропустил и произошло смещение. Понятно что Вы не могли это учесть, поскольку в выложенном куске их нет.
sngr
Спасибо, отличная работа.
Вот что получилось
Код:
$j = 0
		While 1
			$sLine = FileReadLine($File)
			If @error = -1 Then ExitLoop
			$sPattern = '(?m)(?<=^|,)(?:"[^"\r\n]*+"|[^,"\r\n])*+'
			$aArrayLine	= StringRegExp($sLine, $sPattern, 3)
			For $i = 0 to UBound($aArrayLine) - 1
				$aArrayOUT[$j][$i] = $aArrayLine[$i]
			Next
			$j += 1
		WEnd
Собственно, все это задумано для перевода csv в xls, с последующим форматированием столбцов. С дальнейшим я справлюсь. edyapd, sngr еще раз спасибо!
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
Код:
#include 'array.au3'
$file=FileRead('test.txt')
$str=StringRegExp($file,'(?m)(?<=^|,)(?:"[^"\r\n]*+"|[^,"\r\n])*+',3)
_ArrayDisplay($str)

Вот всё что нужно. Никакой нужды читать файл построчно нет.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
sngr сказал(а):
Код:
$str=StringRegExp($file,'(?m)(?<=^|,)(?:"[^"\r\n]*+"|[^,"\r\n])*+',3)

Вот всё что нужно. Никакой нужды читать файл построчно нет.
Если бы вы ещё расшифровали, то был бы очень признателен.
Просто я совсем недавно пытаюсь составлять выражения. То что написано у меня, там понятно новичку.
В вашем выражении я дальше второй группы продвинуться не смог.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
ildar,
Можно примерно так сделать.
Код:
#include <Array.au3>

Local $s_File = @ScriptDir & '\1.csv', $sTxt, $i_Columns, $i_Items, $a_Ret[1]

$sTxt = FileReadLine($s_File, 1)
StringRegExpReplace($sTxt, '(?<=^|,)(?:"[^"]*+"|[^,"])*+', '')
$i_Columns = @extended
If Not $i_Columns Then Exit 1
$sTxt = StringStripCR(FileRead($s_File))
$a_Tmp = StringRegExp($sTxt,'(?m)(?<=^|,)(?:"[^"\n]*+"|[^,"\n])*+',3)
$i_Items = UBound($a_Tmp) / $i_Columns
If IsFloat($i_Items) Then Exit 2
$sTxt = ''
ReDim $a_Ret[$i_Items + 1][$i_Columns]
For $i = 0 To $i_Items * $i_Columns - 1 Step $i_Columns
	$a_Ret[0][0] += 1
	For $j = 0 To $i_Columns - 1
		$a_Ret[$a_Ret[0][0]][$j] = StringReplace($a_Tmp[$i + $j], '"', '')
	Next
Next
$a_Tmp = 0
_ArrayDisplay($a_Ret)
Поправил код, предыдущий вариант у меня работал в AutoIt v3.3.8.1 и не работал в AutoIt v3.3.12.0 :scratch:
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
http://www.autoitscript.com/forum/topic/144961-csv-viewer/?p=1023504
 
Автор
ildar

ildar

Осваивающий
Сообщения
252
Репутация
29
sngr сказал(а):
Код:
#include 'array.au3'
$file=FileRead('test.txt')
$str=StringRegExp($file,'(?m)(?<=^|,)(?:"[^"\r\n]*+"|[^,"\r\n])*+',3)
_ArrayDisplay($str)

Вот всё что нужно. Никакой нужды читать файл построчно нет.
Мне нужен двумерный массив, по этому читаю построчно.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
ildar сказал(а):
sngr сказал(а):
Вот всё что нужно. Никакой нужды читать файл построчно нет.
Мне нужен двумерный массив, по этому читаю построчно.
А вы всё таки попробуйте.
Хотя признаться я с ходу ещё не разобрался как это работает. Жду, может автор расшифрует.
 

AleXXX34

Новичок
Сообщения
1
Репутация
0
можно так в двумерный массив:
Код:
#include <String.au3>
#include <Array.au3>


Dim $box[2000][20]  ;двумерный массив ячеек, 2000 строк, 20 столбцов
Dim $ya[20]                           
Dim $aRecords
_FileReadToArray("test.txt",$aRecords)
	For $XkolX = 1 to $aRecords[0]
	Next
; разделяем строки по ячейкам
For $ia = 1 To $aRecords[0]                            
	$ya = StringSplit ($aRecords[$ia], "," )    ; ставим разделитель, если TAB то @TAB, если запятая то "," и тд и тп
	$nya = $ya[0]
For $k = 1 To $nya
	$box[$ia][$k] = $ya [$k]
Next
Next
_ArrayDisplay($box)]
 
Верх