Войти

Показать полную графическую версию : Задать соответствие точному количеству и регистру символов.


temphard
29-12-2019, 15:56
Здравствуйте. Для замены целой/части строки я использую данный скрипт:
$samples = Import-Csv '1.txt' -Encoding UTF8 -Delimiter ' ' -Header 'P1','P2' | select @{N='P1';E = {[regex]::Escape($_.P1)}},P2
$InFile = '2.txt'
$OutFile = 'out.txt'

# $JobCount = (gwmi win32_processor | measure NumberOfCores -S).Sum

$JobCount = 4 # количество одновременно выполняющихся скрипт-блоков $Job_ReplaceText
$TextBlockSize = 10000 # по сколько строк считывать для параллельной обработки в каждом скрипт-блоке $Job_ReplaceText

$Job_ReplaceText =
{
foreach($sample in $args[1])
{
$args[0] = $args[0] -replace $sample.P1,$sample.P2
}
Return $args[0]
}

$n = 1
$null | Set-Content $OutFile

foreach ($block in Get-Content $InFile -ReadCount $TextBlockSize -Encoding UTF8)
{
Start-Job -Name "Replace-$(($n++))" -ArgumentList $block,$samples -ScriptBlock $Job_ReplaceText

if ($n -gt $JobCount)
{
$n = 1
Get-Job Replace-* | Wait-Job | sort Name | Receive-Job | Add-Content $OutFile -Encoding UTF8
Get-Job Replace-* | Remove-Job
}
}

Get-Job Replace-* | Wait-Job | sort Name | Receive-Job | Add-Content $OutFile -Encoding UTF8
Get-Job Replace-* | Remove-Job
Проблема в том, что скрипт не чувствителен к регистру и точности строки/части, которую необходимо заменить.
Например в файле 1.txt подготовлены строки для замены (вначале стоит то, что искать а через пробел то, чем это заменить):
textstroka1 newstroka1text
textstroka2 newstroka2text
textstroka3 newstroka3text
textstroka4 newstroka4text
textstroka5 newstroka5text
textstroka6 newstroka6text
textstroka7 newstroka7text
textstroka8 newstroka8text
textstroka9 newstroka9text
textstroka10 newstroka000text
textstroka11 newstroka0000text
В файле 2.txt содержится текст:
textstroka1
textStroka2
textsTroka3
textstRoka4
textstrOka5
textstroka6
textstroka7
textstroka8
textstroka9
textstroka10
textstroka11
Результат работы скрипта получается такой, то есть строки 2,3,4 и 5 не должны быть изменены, так как регистр некоторых букв не соответствует, поисковому запросу. Кроме того строки 10 и 11 заменены некорректно, потому что не учтены все символы при поиске:
newstroka1text
newstroka2text
newstroka3text
newstroka4text
newstroka5text
newstroka6text
newstroka7text
newstroka8text
newstroka9text
newstroka1text0
newstroka1text1
Задача состоит в том, чтобы скрипт выдавал следующее:
newstroka1
textStroka2
textsTroka3
textstRoka4
textstrOka5
newstroka6
newstroka7
newstroka8
newstroka9
newstroka000text
newstroka0000text
Можно ли подправить данный скрипт, чтоб он производил замену в точности учитывая количество и регистр символов?

Busla
29-12-2019, 20:40
используйте метод replace вместо оператора -replace

DJ Mogarych
29-12-2019, 23:26
$samples = Import-Csv 'C:\temp\3\1.txt' -Encoding UTF8 -Delimiter ' ' -Header 'P1','P2'
$InFile = gc 'C:\temp\3\2.txt'

$OutFile = foreach ($string in $infile) {
if ($string -cin $samples.p1) {
($samples |? p1 -ceq $string).p2
}
else {$string}
}

$OutFile |Out-File 'C:\temp\3\out.txt' -Encoding UTF8

temphard
30-12-2019, 01:25
используйте метод replace вместо оператора -replace »
Вы хотели сказать: оператор -replace заменить на -creplace
Спасибо. С регистром все наладилось, а проблема с почти одинаковыми строками осталась.

YuS_2
30-12-2019, 08:05
if ($string -cin $samples.p1) {
($samples |? p1 -ceq $string).p2
} »
- это не подойдет для случая:
Для замены ...части строки »


Задача состоит в том, чтобы скрипт выдавал следующее »
по-моему, судя по условию, в Вашем результате ошибка...
Попробуйте:
$frep = 'd:\test\1.txt'
$fin = 'd:\test\2.txt'
$fout = 'd:\test\out.txt'
[array]$arr = import-csv $frep -enc utf8 -del ' ' -h 'p1','p2'

gc $fin -enc utf8|%{
$tmp = $_
for ($i=0;$i -lt $arr.length;$i++){
if($tmp -cmatch "\b$($arr[$i].p1)\b"){
$tmp = $tmp -creplace $arr[$i].p1,$arr[$i].p2
}
}
$tmp
} #|sc $fout -enc utf8
- если вывод в консоль правильный, то удалите символ комментария в последней строке и вывод будет перенаправлен в файл.

Busla
30-12-2019, 11:19
Цитата Busla:
используйте метод replace вместо оператора -replace »
Вы хотели сказать: оператор -replace заменить на -creplace »
Я сказал ровно то, что хотел сказать. Операторы -replace и -creplace работают с регулярными выражениями.
Простая замена строк реализована в методе:
'AaBcCc'.replace('a','z')

YuS_2
30-12-2019, 13:34
работают с регулярными выражениями »
по той же причине:
Для замены ...части строки »
без регулярок, обойтись будет трудно...

textstroka1
textStroka2
textsTroka3
textstRoka4
textstrOka5
textstroka6
textstroka7
textstroka8
textstroka9 textstroka11
textstroka10
textstroka11

temphard
31-12-2019, 00:37
без регулярок, обойтись будет трудно »
Согласен. Поэтому в дальнейшем решил избегать одинаковых строк textstroka1 textstroka11.
Просто использую цифры от 1 до 9 а дальше буквы алфавита:
textstroka1
textstroka2
textstroka3
textstroka4
textstroka5
textstroka6
textstroka7
textstroka8
textstroka9
textstrokaА
и т.д.
В итоге код с задачей справляется.
Всем спасибо за помощь и участие.




© OSzone.net 2001-2012