none
Объединение двух csv файлов с помощью PowerShell. RRS feed

  • Вопрос

  • Добрый день!

    Есть два файла csv. 

    Первый:

    "name", "id"
    "Green","123"
    "Blue","223"
    "Red","323"
    "Black","423"
    "White","523"


    И второй:

    "id","value"
    "123","100"
    "223","33"
    "323","50"
    "423","21"
    "523","156"


    В первом файле необходимо создать новый столбец с именем "value".  Далее необходимо по строково сравнить оба файла по столбцу "id" и при совпадении, записать значение столбца "value" из второго файла.

    В итоге первый csv должен получиться следующего вида:

    "name", "id","value"
    "Green","123","100"
    "Blue","223","33"
    "Red","323","50"
    "Black","423","21"
    "White","523","156"


     



    • Изменено Mr.Rudgar 11 февраля 2013 г. 7:01
    11 февраля 2013 г. 6:59

Ответы

  • $hash = @{}
    Import-CSV f1.csv | Foreach {$hash[$_.id] = $_.name}
    $f2 = Import-CSV f2.csv
    
    $f2 | Foreach { if($hash[$_.id]) { 
    		$obj = "" | Select "name",id,value
    		$obj.Name = $hash[$_.id]
    		$obj.Id = $_.id
    		$obj.value= $_.value
    		$obj
    	}
    } | Export-CSV -NoType result.csv
    

    • Помечено в качестве ответа Mr.Rudgar 11 февраля 2013 г. 20:01
    11 февраля 2013 г. 7:35
    Отвечающий

Все ответы

  • $hash = @{}
    Import-CSV f1.csv | Foreach {$hash[$_.id] = $_.name}
    $f2 = Import-CSV f2.csv
    
    $f2 | Foreach { if($hash[$_.id]) { 
    		$obj = "" | Select "name",id,value
    		$obj.Name = $hash[$_.id]
    		$obj.Id = $_.id
    		$obj.value= $_.value
    		$obj
    	}
    } | Export-CSV -NoType result.csv
    

    • Помечено в качестве ответа Mr.Rudgar 11 февраля 2013 г. 20:01
    11 февраля 2013 г. 7:35
    Отвечающий
  • $hash = @{}
    Import-CSV f1.csv | Foreach {$hash[$_.id] = $_.name}
    $f2 = Import-CSV f2.csv
    
    $f2 | Foreach { if($hash[$_.id]) { 
    		$obj = "" | Select "name",id,value
    		$obj.Name = $hash[$_.id]
    		$obj.Id = $_.id
    		$obj.value= $_.value
    		$obj
    	}
    } | Export-CSV -NoType result.csv
    

    Спасибо! То, что надо.
    11 февраля 2013 г. 20:02
  • Добрый день.

    А как быть в случае если в первом файле больше 2-х столбцов? Например:

    "name", "id","year"
    "Green","123", "2012"
    "Blue","223", "2012"
    "Red","323", "2013" 
    "Black","423", "2013" 
    "White","523" , "2010" 

    Или в обоих файлах больше чем 2 стоблца, каким образом их тогда объединять 

    23 сентября 2013 г. 12:14
  • Добрый день.

    А как быть в случае если в первом файле больше 2-х столбцов? Например:

    "name", "id","year"
    "Green","123", "2012"
    "Blue","223", "2012"
    "Red","323", "2013" 
    "Black","423", "2013" 
    "White","523" , "2010" 

    Или в обоих файлах больше чем 2 стоблца, каким образом их тогда объединять 


    Приведите пример обоих csv файлов.
    23 сентября 2013 г. 14:57
    Отвечающий
  • Стояла задача учета входа - выхода в систему. При помощи LogParser смог получить csv файл с 4-мя полями: Date, SamAccountName, Logon,Logoff Но надо было вместо логинов показать ФИО сотрудников. Как это сделать средствами LogParser я так и не понял и решил воспользоваться скриптом который нашел на этой странице. Данный скрипт, в том виде что у вас, в csv выводил System.Object[] вместо значений. Я ни как не мог прочитать данные из массива $hash[$_.id]. После долгих поисков нашел способ обратиться к этим данным, в моем случае $obj.Date = @($hash[$_.SamAccountName])[0] который и выводил только значение поля Date


    f1.csv:
    SamAccountName,Date,Logon,Logoff
    Administrator,2013-09-24,09:30:22,11:01:04
    Administrator,2013-09-24,00:53:24,09:51:09
    test1,2013-09-24,10:03:44,10:38:34


    f2.csv:
    SamAccountName,Name
    Administrator,Администратор
    test1,Пользователь 1


    Скрипт объеденения 2-х csv файлов по полю SamAccountName:
    Import-CSV c:\f1.csv | Foreach {$hash[$_.SamAccountName] = $_.Date, $_.Logon, $_.Logoff}
    $f2 = Import-CSV c:\f2.csv
    $f2 | Foreach { if($hash[$_.SamAccountName]) {
    $obj = "" | Select Date, SamAccountName, Name, Logon,Logoff
    $obj.Date = @($hash[$_.SamAccountName])[0]
    $obj.SamAccountName = $_.SamAccountName
    $obj.Name = $_.Name
    $obj.Logon = @($hash[$_.SamAccountName])[1]
    $obj.Logoff = @($hash[$_.SamAccountName])[2]
    $obj
    }
    } | Export-CSV -NoType c:\f3.csv -Encoding utf8

    Возможно есть более простые пусти решения. Буду благодарен за помощь.

    24 сентября 2013 г. 7:29
  • Как вариант:

    $f1 = Import-Csv f1.csv
    Import-Csv f2.csv | Foreach {$f1 -match $_.SamAccountName | Add-Member -Type NoteProperty -Value $_.Name -Name Name -PassThru}

    24 сентября 2013 г. 7:43
    Отвечающий
  • Скрипт выбирает значение поля для user1 и user10 из f2.csv равное "пользователь 1"

    f1.csv:
    SamAccountName,Date,Logon,Logoff
    user1,24.09.2013,0:02:50,10:19:01
    user2,24.09.2013,8:17:27,11:18:02
    user3,24.09.2013,10:04:11,11:05:03
    user4,24.09.2013,8:51:28,9:55:04
    user5,24.09.2013,9:16:25,11:18:05
    user6,24.09.2013,9:19:03,11:02:06
    user7,24.09.2013,0:42:04,10:43:07
    user8,24.09.2013,8:40:25,11:05:08
    user9,24.09.2013,1:05:24,10:57:09
    user10,24.09.2013,9:22:38,11:06:10


    f2.csv:
    "user1","Пользователь 1"
    "user2","Пользователь 2"
    "user3","Пользователь 3"
    "user4","Пользователь 4"
    "user5","Пользователь 5"
    "user6","Пользователь 6"
    "user7","Пользователь 7"
    "user8","Пользователь 8"
    "user9","Пользователь 9"
    "user10","Пользователь 10"

    то получается:
    "user1","24.09.2013","0:02:50","10:19:01","Пользователь 1"
    "user10","24.09.2013","9:22:38","11:06:10","Пользователь 1"
    "user2","24.09.2013","8:17:27","11:18:02","Пользователь 2"
    "user3","24.09.2013","10:04:11","11:05:03","Пользователь 3"
    "user4","24.09.2013","8:51:28","9:55:04","Пользователь 4"
    "user5","24.09.2013","9:16:25","11:18:05","Пользователь 5"
    "user6","24.09.2013","9:19:03","11:02:06","Пользователь 6"
    "user7","24.09.2013","0:42:04","10:43:07","Пользователь 7"
    "user8","24.09.2013","8:40:25","11:05:08","Пользователь 8"
    "user9","24.09.2013","1:05:24","10:57:09","Пользователь 9"

    24 сентября 2013 г. 12:00
  • Тогда заменить на: -match "\b$($_.SamAccountName)\b"
    24 сентября 2013 г. 12:19
    Отвечающий
  • Помогло.

    Спасибо.

    24 сентября 2013 г. 12:46
  • Здравствуйте, у меня такая же проблема, нужно объединить 2 файла csv с поиском строк по ID, я переделал скрипт но значения пустые. Посмотрите пожалуйста что не так?

    Import-CSV c:\6\1.csv | Foreach {$hash[$_.ID] = $_.TB, $_.Number}
    $f2 = Import-CSV c:\6\2.csv
    $f2 | Foreach { if($hash[$_.ID]) { 
    $obj = "" | Select ID, TB, Number
    $obj.TB = @($hash[$_.ID])[0]
    $obj.Number = $_.ID

    $obj
    }
    } | Export-CSV -NoType c:\6\f3.csv -Encoding utf8

    Файл 1

    ID - TB - Number
    01 , SB , 24
    12 , DV , 63

    Файл 2
    ID-UR1-UR2
    01 , soft , install soft
    12 , soft , uninstall soft

    Итоговый файл

    ID - TB - Number - UR1 - UR2
    01:01 - SB - 24 - soft - install soft
    12:04 - DV - 63 - soft - uninstall soft




    • Изменено Aleks Roth 5 августа 2016 г. 13:09
    5 августа 2016 г. 12:47
  • Кодировка файла Unicode и формат,ниже:

    # Первый файл
    PS (STA) > Get-Content 1.csv
    ID,TB,Number
    01,SB,24
    12,DV,63
    
    # Второй файл
    PS (STA) > Get-Content 2.csv
    ID,UR1,UR2
    01,soft,"install soft"
    12,soft,"uninstall soft"

    Скрипт:

    $hash = @{}
    Import-CSV 1.csv | Foreach {$hash[$_.ID] = $_.TB, $_.Number}
    Import-CSV 2.csv| Foreach { 
    	if($hash[$_.ID]) { 
    		$obj = "" | Select ID, TB, Number, UR1 , UR2
    		$obj.TB = @($hash[$_.ID])[0]
    		$obj.ID = $_.ID
    		$obj.Number = @($hash[$_.ID])[1]
    		$obj.UR1 = $_.UR1
    		$obj.UR2 = $_.UR2
    
    		$obj
    	}
    } | Export-CSV -NoType 3.csv -Encoding utf8 -Delimiter "-"


    Вывод:

    "ID"-"TB"-"Number"-"UR1"-"UR2"
    "01"-"SB"-"24"-"soft"-"install soft"
    "12"-"DV"-"63"-"soft"-"uninstall soft"

    Если надо без " и пробел между -:

    $hash = @{}
    Import-CSV 1.csv | Foreach {$hash[$_.ID] = $_.TB, $_.Number}
    Import-CSV 2.csv| Foreach { 
    	if($hash[$_.ID]) { 
    		$obj = "" | Select ID, TB, Number, UR1 , UR2
    		$obj.TB = @($hash[$_.ID])[0]
    		$obj.ID = $_.ID
    		$obj.Number = @($hash[$_.ID])[1]
    		$obj.UR1 = $_.UR1
    		$obj.UR2 = $_.UR2
    
    		$obj
    	}
    } | ConvertTo-CSV -NoType -Delimiter "-" | Foreach {$_ -replace '"' -replace "-"," - "} | Out-File 3.csv -Encoding utf8

    Вывод:

    ID - TB - Number - UR1 - UR2
    01 - SB - 24 - soft - install soft
    12 - DV - 63 - soft - uninstall soft

    5 августа 2016 г. 13:20
    Отвечающий
  • Прошу прощения, указал неправильно, без разницы с кавычками или без, главное чтобы экспортировались данные, каждый в своем столбце, в таком порядке: 

    ID, TB, Number,UR1,UR2

    01,SB,24,soft,install soft

    Не могу разобраться, формируется csv, но он пустой, ошибка следующая:

    Сбой операции индексирования, индекс массива вычислен как NULL.
    строка:4 знак:5
    +     if($hash[$_.ID]) {
    +        ~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : NullArrayIndex


    6 августа 2016 г. 0:41