2015-05-25 5 views
0

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

Для Ex: Мой текстовый файл содержит:

cd $home/t17_0/download/functional-tests/ 
ant compile-all 
cd $home/15_5/download/functional-tests/ 
ant compile-all 
cd $home/15_7/download/functional-tests/ 
ant compile-all 

Я хочу, чтобы матч с линией cd $home/15_5/download/functional-tests/ (линия № 3) и добавить cd $home/15_6/download/functional-tests/ после муравой компиляции всех (линия № 4). Обратите внимание, что в моем реальном сценарии я не знаю номер строки.

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

$mat='cd $home/15_5/download/functional-tests/' 
$add='cd $home/15_6/download/functional-tests/' 
$file_content=get-content text.txt 
($file_content) | foreach-object { 
    $_ 
    if ($_ -contains $mat) 
    { 
     $add 
    } 
}| set-content $file_content 

Это соответствие линии с cd $home/15_5/download/functional-tests/ (линия № 3) и добавляет cd $home/15_6/download/functional-tests/ до того ant compile-all (номер строки 4) ,

+0

Извините, я скопировал только эту конкретную строку из сценария, теперь я обновил вопрос. @AnsgarWiechers: Да, это мой вопрос, я хочу вставить строку 2 строки после соответствующей строки. Я написал сценарий, как показано ниже, но я ищу лучшее решение. $ Ant = 'ant compile-all' $ file_content = get-content text.txt ($ file_content) | foreach-object {$ _ if ($ _ -contains $ mat) {$ ant $ add}} | set-content $ file_content , который дал мне результат, как ожидалось, добавив эти 2 строки после строки 3: , но я ищу лучшее решение, я не хочу объявлять и добавлять 'ant compile-all' в свой скрипт. Спасибо – peer

ответ

1

Существует несколько способов сделать это. Например, вы могли бы использовать регулярное выражение:

$file = 'C:\path\to\your.txt' 

$mat = 'cd $home/15_5/download/functional-tests/' 
$add = 'cd $home/15_6/download/functional-tests/' 

$pattern = "(?m)(" + [regex]::escape($mat) + "`r`nant compile all)" 

(Get-Content $file -Raw) -replace $pattern, "`$1`r`n$add" | 
    Set-Content $file 

или StreamReader:

$file = 'C:\path\to\your.txt' 

$mat = 'cd $home/15_5/download/functional-tests/' 
$add = 'cd $home/15_6/download/functional-tests/' 

$reader = [IO.File]::OpenText($file) 

$text = while ($reader.Peek() -ge 0) { 
      $line = $reader.ReadLine() 
      $line 
      if ($line -eq $mat) { 
      $reader.ReadLine() 
      $add 
      } 
     } 
$reader.Close() 

$text | ? { $_ } | Set-Content $file 

? { $_ } фильтра выше является гарантией предотвращения файла от усечены в случае $text пусто.

+0

Спасибо Ansgar, второе решение, использующее StreamReader, работает на меня. – peer

0

Когда вы используете Get-Content, каждая строка имеет Readcount, мы можем использовать это, чтобы найти строку, соответствующую вашему тексту, а затем выводить строки обратно в файл. Также нам нужно избежать текста $toMatch, так как он содержит управляющие символы регулярного выражения ($).

$toMatch = [regex]::Escape('cd $home/15_5/download/functional-tests/') 
$toAdd = 'cd $home/15_6/download/functional-tests/' 
$fileData = Get-Content $pathtofile 
$matchedLineNumber = $fileData | Where-Object{$_ -match $toMatch} | Select-Object -Expand ReadCount 

$fileData | ForEach-Object{ 
    $_ 
    If($_.ReadCount -eq ($matchedLineNumber + 1)){ 
     $toAdd 
    } 
} | Set-Content $pathtofile 

Если файл большой, то используя что-то вроде в Ansgar's Answer будет более эффективным. $matchedLineNumber содержит номер строки, где мы находим текст. Затем, находясь внутри цикла, мы ищем следующую строку (где используется +1). После обнаружения этого совпадения мы выводим дополнительный текст $toAdd.

-contains

Это один из подводных камней в PowerShell. Посмотрите на this answer, чтобы понять, как это предполагается для использования.

Смежные вопросы