質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

置換

置換とは文字列中の特定の文字に対して、別の文字列に置き換えることを指します。

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

Q&A

解決済

1回答

575閲覧

Powershell キーワード検索して5行下を置換

HAL0012

総合スコア11

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

置換

置換とは文字列中の特定の文字に対して、別の文字列に置き換えることを指します。

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

1グッド

1クリップ

投稿2019/06/20 12:46

Powershell 初心者で手探りで勉強しながら作っています

フォルダ内の複数のテキストファイル内の
あるキーワードを検索してそのキーワードから5行下に
検索したものとは別のキーワードがある場合は置換、
ない場合は何もしないを繰り返して
元のファイル名と違う名前でそれぞれ出力ということは出来ますか?

Select-string で検索してreplaceで置換すれば出来そうな気は
するのですが、上手くいかないので力を貸して頂ければと思います。

DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/06/20 13:08

できますが、何のためにそれをするんですか?
HAL0012

2019/06/20 22:52

5行下のものだけを指定して置換をすると 置換をしたくないところもしてしまうので、 近くの別のキーワードを検索してから置換出来ればと思った感じです
guest

回答1

0

ベストアンサー

次のスクリプトを untitled.ps1 として保存してください。

ps1

1[CmdletBinding()] 2Param ( 3 [Parameter( 4 Mandatory = $true, 5 Position = 0, 6 ValueFromPipelineByPropertyName = $true 7 )] 8 [regex]$FirstPattern, 9 10 [Parameter( 11 Mandatory = $true, 12 Position = 1, 13 ValueFromPipelineByPropertyName = $true 14 )] 15 [regex]$SecondPattern, 16 17 [Parameter( 18 Mandatory = $true, 19 Position = 2, 20 ValueFromPipelineByPropertyName = $true 21 )] 22 [string]$Replacement, 23 24 [Parameter( 25 Mandatory = $false, 26 Position = 3, 27 ValueFromPipelineByPropertyName = $true 28 )] 29 [ValidateRange(1, [int]::MaxValue)] 30 [int]$Count = 5, 31 32 [Parameter( 33 Mandatory = $true, 34 Position = 4, 35 ValueFromPipelineByPropertyName = $true, 36 ValueFromPipeline = $true, 37 ValueFromRemainingArguments = $true 38 )] 39 [string[]]$InputObject 40) 41Begin { 42 $phase = 0 43} 44Process { 45 if ($phase -eq $Count) { 46 $InputObject -replace $SecondPattern, $Replacement 47 } else { 48 $InputObject 49 } 50 if ($phase -ne 0 -or $_ -match $FirstPattern) { 51 $phase++ 52 } 53}

次にテスト用のデータを作ります。

1..10 | Foreach-Object { "foo","bar" } > old.txt

old.txt を開き、foo bar が交互に 10 回並んでいることを確かめてください。
問題無ければ置換します。

Get-Content .\old.txt | .\untitled.ps1 bar . x

置換結果は画面に表示されます。
7 行目の foo が xxx に置換されているはずです。

.\untitled.ps1 bar . x は三つの引数 bar . x を取ります。
最初の bar は最初に発見する文字列です。
これが二行目にあるので、実際に置換するのはその五行後の七行目ということになります。
. は正規表現で任意の一文字の意味です。これを x に置換します。
この結果、七行目の foo が xxx になります。
これを新しいファイルに保存するには次のようにします。

Get-Content .\old.txt | .\untitled.ps1 bar . x > new.txt

一番目の引数と二番目の引数が正規表現であることに気を付けてください。

追記

二度の仕様追加の要件を満たすもののはずです。これ以降、仕様の追加があるのであれば、この質問は解決済みにして自分で実装してください。それでどうしてもわからなければまた改めて新しい質問を立ててください。

ps1

1[CmdletBinding()] 2Param ( 3 [Parameter( 4 Mandatory = $true, 5 Position = 0, 6 ValueFromPipelineByPropertyName = $true 7 )] 8 [regex]$FirstPattern, 9 10 [Parameter( 11 Mandatory = $true, 12 Position = 1, 13 ValueFromPipelineByPropertyName = $true 14 )] 15 [regex]$SecondPattern, 16 17 [Parameter( 18 Mandatory = $true, 19 Position = 2, 20 ValueFromPipelineByPropertyName = $true 21 )] 22 [string]$Replacement, 23 24 [Parameter( 25 Mandatory = $false, 26 Position = 3, 27 ValueFromPipelineByPropertyName = $true 28 )] 29 [ValidateRange(0, [int]::MaxValue)] 30 [int]$Count = 5, 31 32 [Parameter( 33 Mandatory = $true, 34 Position = 4, 35 ValueFromPipelineByPropertyName = $true, 36 ValueFromPipeline = $true, 37 ValueFromRemainingArguments = $true 38 )] 39 [string[]]$InputObject 40) 41Begin { 42 $replace = @() 43 $line = 1 44} 45Process { 46 if ($InputObject -match $FirstPattern) { 47 $replace += ($line + $Count) 48 } 49 if ($replace -contains $line) { 50 $InputObject -replace $SecondPattern, $Replacement 51 $replace = $replace -gt $line 52 } else { 53 $InputObject 54 } 55 $line++ 56}

投稿2019/06/21 04:04

編集2019/06/21 11:56
Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HAL0012

2019/06/21 07:05

Zuishinさん ありがとうございます。 概ね目的のものが出来たのですが3つほど質問があります。 1 こちらで用意したファイルを置換した際ファイルに改行が入っており 「引数がないため〜」とエラーが出てファイルは出力され置換もされたのですが改行が全部消えてしまいました。回避する方法はありますか? 2 ファイル内に複数の1つ目の引数がある場合それぞれの5行下の2つ目の引数全てを置換するにはどうすればよいですか? 3 今回5行下でお願いしたのですが置換対象の行数を変えたい場合はどこを修正すればよいですか? よろしくお願いします。
Zuishin

2019/06/21 07:20 編集

1. こちらで用意したファイルではうまくいっています。そちらで用意したファイルがわからないのでわかりません。もしかしたら改行コードが Mac 用のものだとうまくいかないかもしれません。その場合は Get-Content の引数 Delimiter を使ってください。 2. 複数回行ってください。パイプが使えます。Get-Content .\old.txt | .\untitled.ps1 bar . x | .\untitled.ps1 foo . y > new.txt 3. 引数 Count を用意しています。untitled -Count 6 で六行下になります。
HAL0012

2019/06/21 09:38

1.3については解決出来ましたありがとうござました 2なのですが、今の状態だと2行目のbarを検索して7行目のfooを置換で終わるので、繰り返しで4行目のbarを検索して9行目のfooを置換、6行目のbarを検索して。。。 というようにファイル内のbarを全て検索して置換を実施したいのですが出来ますか?
Zuishin

2019/06/21 09:43

そうなるとスクリプトを書き換えなければいけませんが、もともとの質問とは違ってきています。
HAL0012

2019/06/21 09:53

作成意図を上手く伝えられなくて申し訳ありませんでした
Zuishin

2019/06/21 11:00 編集

配列は使えますか? 具体的には要素の取得、追加、削除はできますか? コードで答えてください。
Zuishin

2019/06/21 11:40

自分でやってもらおうと思ったけど、こちらでも試してみたら少しハードルが高いような気がしたのでこちらで作り、追記しました。
HAL0012

2019/06/21 12:26

すいません ありがとうござました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問