powershell: добавить текст перед определенной строкой, а не после

Я ищу способ добавить текст перед строкой. Чтобы быть более конкретным, Перед строкой и пробелом. Сейчас скрипты добавляют мой текст после строки [companyusers]. Но я хотел бы добавить строку перед [CompanytoEXT] и перед пробелом над [CompanytoEXT].

Кто-нибудь знает, как это сделать?

Визуальное представление того, что я хотел бы сделать: https://imgur.com/a/lgH5i

Мой текущий скрипт:

$FileName = "C:\temptest\testimport - Copy.txt"
$Pattern = "[[\]]Companyusers"  
$FileOriginal = Get-Content $FileName

[String[]] $FileModified = @() 
Foreach ($Line in $FileOriginal)
{   
    $FileModified += $Line
    if ($Line -match $pattern) 
    {
        #Add Lines after the selected pattern 
        $FileModified += "NEWEMAILADDRESS"

    } 
    }

Set-Content $fileName $FileModified

Спасибо за любой совет!

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


person Niels Frederickx    schedule 05.10.2017    source источник
comment
Основываясь на полезных изображениях, я бы сказал, что ваш вопрос немного вводит в заблуждение. Я думаю, что вставка строки в конце определенного раздела файла ini лучше передаст смысл.   -  person TToni    schedule 05.10.2017


Ответы (2)


Это может быть проще с использованием ArrayList, чтобы вы могли легко вставлять новые данные в определенную точку:

$FileName = "C:\temptest\testimport - Copy.txt"
$Pattern = "[[\]]Companyusers"
[System.Collections.ArrayList]$file = Get-Content $FileName
$insert = @()

for ($i=0; $i -lt $file.count; $i++) {
  if ($file[$i] -match $pattern) {
    $insert += $i-1 #Record the position of the line before this one
  }
}

#Now loop the recorded array positions and insert the new text
$insert | Sort-Object -Descending | ForEach-Object { $file.insert($_,"NEWEMAILADDRESS") }

Set-Content $FileName $file

Сначала откройте файл в ArrayList, затем переберите его. Каждый раз, когда вы сталкиваетесь с шаблоном, вы можете добавить предыдущую позицию в отдельный массив $insert. После завершения цикла вы можете зациклить позиции в массиве $insert и использовать их для добавления текста в ArrayList.

person arco444    schedule 05.10.2017
comment
У меня была такая же установка, но с обычным массивом, что сильно усложняло задачу. Это отличное использование массива (что-то, о чем я только что узнал ранее на этой неделе). Интересно прочитать о arraylist в powershell: mcpmag .com/articles/2017/09/28/ - person Snak3d0c; 05.10.2017
comment
Awsome, спасибо за вашу помощь. Я постараюсь узнать больше о массивах. - person Niels Frederickx; 05.10.2017
comment
Пожалуйста! Пожалуйста, примите ответ, если он помог решить вашу проблему. - person arco444; 05.10.2017
comment
Разве ваша вставка не изменит положение? Итак, если $insert равно 3, 7, и вы вставляете строку в 3, не изменится ли элемент 7? Не сместится ли содержимое с вставки в 3? Я думаю, вам нужно сделать $insert | sort -descending | ForEach-Object [...]. Таким образом, вы начинаете вставлять в конце, а не в начале. - person Bacon Bits; 05.10.2017
comment
@BaconBits да, вы абсолютно правы. Ответ обновлен. - person arco444; 05.10.2017

Здесь вам понадобится небольшая конечная машина. Обратите внимание, когда вы нашли правильный раздел, но еще не вставляйте строку. Вставлять только в следующую пустую строку (или в конец файла, если раздел последний в файле).

Не проверял, но должно выглядеть так:

$FileName = "C:\temptest\testimport - Copy.txt"
$Pattern = "[[\]]Companyusers"  
$FileOriginal = Get-Content $FileName

[String[]] $FileModified = @() 

$inCompanyUsersSection = $false

Foreach ($Line in $FileOriginal)
{   
    if ($Line -match $pattern) 
    {
        $inCompanyUsersSection = $true
    }

    if ($inCompanyUsersSection -and $line.Trim() -eq "")
    {
        $FileModified += "NEWEMAILADDRESS"
        $inCompanyUsersSection = $false
    } 

    $FileModified += $Line
}

# Border case: CompanyUsers might be the last sction in the file
if ($inCompanyUsersSection)
{
    $FileModified += "NEWEMAILADDRESS"
} 

Set-Content $fileName $FileModified

Изменить: если вы не хотите использовать подход «вставка в следующую пустую строку», потому что, возможно, ваш раздел может содержать пустые строки, вы также можете инициировать вставку в начале следующего раздела ($line.StartsWith("[")). Однако это усложнило бы ситуацию, потому что теперь вам нужно смотреть на две строки вперед, что означает, что вы должны буферизовать одну строку перед ее записью. Выполнимо, но некрасиво.

person TToni    schedule 05.10.2017
comment
Привет Ттони, спасибо за ваш ответ. Знаете ли вы, что мне нужно сделать, если у меня уже есть пустое место вверху (прямо под [Companyusers]). И еще одно пустое место внизу? (Это пространство, которое необходимо заполнить новым адресом электронной почты. Я протестировал ваш скрипт, и он работает, вместо пустого пространства внизу заполняется только верхнее поле. Спасибо! - person Niels Frederickx; 05.10.2017
comment
Мой алгоритм на данный момент отслеживает два события: 1. Мы попали в интересный раздел, 2. Наткнулись на пустую строку. Вы можете ввести третье событие 3. Мы попали в новый раздел. Просто проверьте каждую строку на наличие любого из этих условий, а затем наметьте соответствующие действия (вы должны отложить написание пустых строк, пока не убедитесь, что за ними не следует новый раздел). Лично я бы пошел другим путем: прочитал файл в хеш-таблицу, содержащую разделы в качестве ключей и массив строк разделов в качестве значений. Затем измените нужный раздел (ы) и снова запишите их. Обратите внимание, что это может изменить порядок. - person TToni; 05.10.2017