Powershell - Как искать (используя подстановочный знак) и заменять значения в файле CSV? - PullRequest
0 голосов
/ 12 июля 2020

У меня есть файл CSV (только один столбец / поле) с тысячами записей в нем.

Мне нужен способ в Powershell для поиска значения, используя несколько символов, за которыми следует подстановочный знак и, где найдено, затем замените это значение на ".

Я искал, как это сделать, но все, что я нашел до сих пор, либо не охватывает файлы CSV, либо не объясняет, как я мог бы выполните поиск, используя подстановочный знак.

Пример значений в файле CSV:

<#

RanDom.Texto 1.yellow [ Table - wood ] "gibberishcode1.moreRandomText11.xyz123+456"
R@ndomEq.Textolo 2.blue [Chair - steel ] "gibberishcode2.moreRandomText222.xyz19283+4567+89
randomi.Textpel 3.green [ counter - granite] "gibberishcode3.moreRandomText3333.xyz17243+3210+987+654"

#>

Вы заметите, что единственными общими значениями в записях являются .xyz в каждой записи.

Я хочу заменить .xyz (и все последующее) значением ".

Например, желаемый результат выглядит следующим образом:

<#

RanDom.Texto 1.yellow [ Table - wood ] "gibberishcode1.moreRandomText11"
R@ndomEq.Textolo 2.blue [Chair - steel ] "gibberishcode2.moreRandomText222"
Randomi.Textpel 3.green [ counter - granite] "gibberishcode3.moreRandomText3333"

#>

Вот код, который я пробовал, но он не работает, так как не заменяет значения (но он успешно экспортировать в новый файл csv).

# Create function that gets the current file path (of where this script is located)
function Get-ScriptDirectory {Split-Path -parent $PSCommandPath}

# Create function that gets the current date and time in format of 1990-07-01_19h15m59
function Get-TimeStamp {return "{0:yyyy-MM-dd}_{0:HH}h{0:mm}m{0:ss}" -f (Get-Date)}

# Set current file path. Also used in both FOR loops below as primary source directory.
${sourceDirPath} = Get-ScriptDirectory

# Import CSV look-up file 
${csvFile} = (Import-Csv -Path ${sourceDirPath}\SourceCSVFile.csv)
    
# for each row, replace the values of .xyz and all that follows with "
foreach(${row} in ${csvFile}) 
{
    ${row} = ${row} -replace '.xyz*','"'
}

# Set modified CSV's name and path
${newCSVFile} = ${sourceDirPath} + '\' + $(Get-TimeStamp) + '_SourceCSVFile_Modified.csv'

# export the modified CSV
${csvFile} | Export-Csv ${newCSVFile} -NoTypeInformation

Я тоже пробовал это как альтернативу, но не повезло либо (я думаю, что этот код ниже может работать только для файлов .txt ??) ...

((Get-Content -path C:\TEMP\TEST\SourceCSVFile.csv -Raw) -replace '.xyz'*,'"') | Export-Csv -Path C:\TEMP\TEST\ReplacementFile.csv

Я новичок в Powershell и еще не имею надлежащего понимания регулярных выражений, поэтому, пожалуйста, будьте осторожны .

ОБНОВЛЕНИЕ и РЕШЕНИЕ:

Для тех, кто заинтересован в моем окончательном решении ... Я использовал код, предоставленный Томасом (спасибо !!), однако мой В файле .csv остались записи с тройной кавычкой """ значение в конце строки.

Таким образом, я изменил код, чтобы использовать переменные и выполнить второй проход очистки, заменив все значения тройных кавычек (например, "" ") с одинарными кавычками (например,"), а затем передача результата в файл.

# Create function that gets the current file path (of where this script is located and running from)
function Get-ScriptDirectory {Split-Path -parent $PSCommandPath}

# Set current file path
${sourceDirPath} = Get-ScriptDirectory

# Assign source .csv file name to variable
$origNameSource = 'AllNames.csv'

# Assign desired .csv file name post cleaning
$origNameCLEAN = 'AllNames_CLEAN.csv'
    
# First pass clean to replace .xyz* with " and assign result to tempCsvText variable
${tempCsvText} = ((Get-Content -Path ${sourceDirPath}\$origNameSource) | % {$_ -replace '\.xyz.*$', '"'})

# Second pass clean to replace """ with " and write result to a new .csv file
${tempCsvText} -replace '"""', '"' | Set-Content -Path ${sourceDirPath}\$origNameCLEAN

# Import records from new .csv file and remove duplicates by using Sort-Object * -Unique
${csvFile} = (Import-Csv -Path ${sourceDirPath}\$origNameCLEAN) | Sort-Object * -Unique

1 Ответ

1 голос
/ 12 июля 2020

Во-первых, файл .csv - это не что иное, как обычный текстовый файл, просто следуя некоторым правилам встраивания содержимого (одна строка для каждой строки, столбцы, разделенные определенным символом ASCII, необязательный заголовок). Ваша последняя строчка близка. Вы должны использовать регулярное выражение, которое доходит до конца строки. Это сделает это:

Get-Content -Path C:\TEMP\TEST\SourceCSVFile.csv | % {$_ -replace '\.xyz.*$', '"'} | Set-Content -Path C:\TEMP\TEST\ReplacementFile.csv

Различия:

  • Я удалил параметр -Raw, чтобы каждая строка отображалась как одна строка.
  • Я использовал канал для обработки каждой строки (строки)
  • Я настроил ваше регулярное выражение, чтобы оно соответствовало от .xyz до конца каждой строки
  • Я передал результат в Set-Content, поскольку я только заменил текст и не читал никаких объектов, которые затем нужно было бы повторно перевести обратно в текст csv с помощью Export-Csv
...