<# : バッチコマンド(PowerShellコメント)開始
@echo off & setlocal
rem
rem 正規表現を用いたテキスト複数行検索
rem
rem
rem RegExS.bat [正規表現] [検索対象フォルダー] [ファイル名のフィルター]
rem [-e 文字コード種別] [-g グループ名/番号]
rem [-h] [-i] [-n] [-r] [-s] [-x 除外フィルター]
rem [-bc マッチ箇所の背景色] [-cc マッチ箇所(キャプチャグループ)の文字色]
rem [-fc マッチ箇所の文字色] [-Q/-Interactive]
rem
rem
rem 正規表現 .NET準拠の正規表現を指定します。
rem ※ "^"と"$"はそれぞれ行頭と行末にマッチします。
rem ※ "."を改行文字にもマッチさせるためには先頭に"(?s)"を付加
rem してください。
rem 指定がない場合は入力プロンプトが表示されます。
rem 検索対象フォルダー 指定がない場合は選択ダイアログボックスが表示されます。
rem 対象ファイル名 対象ファイル名をカンマ区切りで指定します。ワイルドカードの
rem 使用が可能です。既定値は"*"です。(例: "*.c, *.h")
rem -e 文字コード種別 BOM(Byte Order Mark)のないファイルの文字コード。(例: "UTF8")
rem -g キャプチャグループ キャプチャグループの名前または番号を指定します。既定値は"0"です。
rem -h HTMLファイルを出力します。
rem -i 検索時に大文字小文字を区別しません。
rem -n 全角文字を半角文字に変換してから検索します。
rem カナ・数字の全角/半角を区別したくない場合に使用します。
rem -r サブフォルダーに対する再帰的検索のスイッチです。
rem -s 単純文字列検索のスイッチです。
rem -x 除外フィルター 除外ファイル名をカンマ区切りで指定します。ワイルドカードの
rem 使用が可能です。(例: "*.img, *.dat")
rem なお、以下のバイナリ形式ファイルは既定で除外されます。
rem "*.exe, *.dll, *.lnk, *.zip, *.bmp, *.gif, *.jpg, *.png"
rem -bc ConsoleColor マッチ箇所の背景色
rem -cc ConsoleColor マッチ箇所(キャプチャグループ)の文字色
rem -fc ConsoleColor マッチ箇所の文字色
rem -Q 対話モードを強制します。
rem
rem 備考:.docx/.pptx/.xlsx/.xlsm 形式のファイルにも実験的に対応しています。
rem 更に、本スクリプトの設置フォルダー内に itextsharp.dll が存在する場合は
rem PDFファイルの検索も可能です。(ラスタ化された文字列やEXCELの数値・日付を除く。)
rem
rem Created by earthdiver1
rem Version 2.00
rem クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。
rem
rem ----------------------------------------------------------------------------
echo %CMDCMDLINE% | findstr /i /c:"%~nx0" >NUL && set DC=1
rem 以下はPowerShellスクリプトをバッチファイルの中に埋め込むためのプリアンブルです。
rem デバッグ時は拡張子を.ps1に変更してPowerShellコンソール上から実行してください。
set BATCH_ARGS=%*
if defined BATCH_ARGS set BATCH_ARGS=%BATCH_ARGS:"=\"%
if defined BATCH_ARGS set BATCH_ARGS=%BATCH_ARGS:^^=^%
set P_CMD=$DoubleClicked=0%DC%;$PSScriptRoot='%~dp0'.TrimEnd('\');$input^|^
&([ScriptBlock]::Create((${%~f0}^|Out-String)))
endlocal & PowerShell -NoProfile -Command "%P_CMD%" %BATCH_ARGS%
exit/b
rem ----------------------------------------------------------------------------
: バッチコマンド(PowerShellコメント)終了 #>
#Requires -Version 3
param (
[String]$Pattern,
[String]$Dir,
[String]$Include = "*",
[Alias("e")][String]$Encoding = "Default",
[Alias("x")][String]$Exclude = "",
[Alias("g")][String]$Group = "0",
[Alias("h")][Switch]$HtmlOutput = $False,
[Alias("i")][Switch]$IgnoreCase = $False,
[Alias("n")][Switch]$Narrow = $False,
[Alias("r")][Switch]$Recurse = $False,
[Alias("s")][Switch]$SimpleMatch = $False,
[Alias("bc")][ConsoleColor]$BackgroundColor = "Blue",
[Alias("cc")][ConsoleColor]$CapturegroupColor = "Red",
[Alias("fc")][ConsoleColor]$ForegroundColor = "White",
[Alias("Q")][Switch]$Interactive = $False
)
#$DebugPreference = "Continue"
Function RegExS {
<#
.SYNOPSIS
正規表現を用いたテキスト検索をおこないます。
.DESCRIPTION
フォルダーツリーの中の複数のテキストファイルに対して正規表現による一括検索を
おこなうことができます。複数行に渡るパターンにマッチする検索が可能です。
.PARAMETER Pattern
正規表現の文字列です。"^" や "$" は行頭・行末にマッチします。
"."(ピリオド)を改行文字(\n)にもマッチさせるためには先頭に(?s)を付加して
ください。
.PARAMETER Dir
検索対象のフォルダーのパスを指定します。
.PARAMETER Include
対象ファイル名をカンマ区切りで指定します。ワイルドカードの使用が可能で、
既定値は"*"です。(例:"*.cpp, *.h")
.PARAMETER Encoding
BOM(Byte Order Mark)の無いテキストファイルの文字コードを指定します。
規定値は"Default"です。(別名: -e)
.PARAMETER BackgroundColor
マッチ箇所の背景色を指定します。(別名: -bc)
規定値は "Blue" です。
.PARAMETER CapturegroupColor
マッチ箇所(キャプチャグループ)の文字色を指定します。(別名: -cc)
規定値は "Red" です。
.PARAMETER ForegroundColor
マッチ箇所の文字色を指定します。(別名: -fc)
規定値は "White" です。
.PARAMETER Group
キャプチャグループの名前または番号を指定します。(別名: -g)
規定値は "0" です。
.PARAMETER HtmlOutput
本スイッチの指定時にはHTMLファイルを出力します。(別名: -h)
.PARAMETER IgnoreCase
本スイッチの指定時には大文字、小文字を区別しません。(別名: -i)
.PARAMETER Narrow
本スイッチの指定時には検索前に全角文字を半角文字に変換します。(別名: -n)
カナ・数字の全角/半角を区別したくない場合に使用します。
.PARAMETER Recurse
本スイッチの指定時にはサブフォルダー内を再帰的に検索します。(別名: -r)
.PARAMETER SimpleMatch
本スイッチの指定時には単純な文字列検索をおこないます。(別名: -s)
.PARAMETER Exclude
除外ファイル名をカンマ区切りで指定します。(別名: -x)
ワイルドカードの使用が可能です。(例: "*.img, *.dat")
なお、以下のバイナリ形式ファイルは既定で除外されます。
*.exe, *.dll, *.lnk, *.zip, *.bmp, *.gif, *.jpg, *.png
.NOTES
Author: earthdiver1
Version: V2.00
クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。
.EXAMPLE
./RegExS.ps1 """(?:[^""\\\n]|\\.)*""|'(?:[^'\\\n]|\\.)*'|(/\*[\S\s]*?\*/|//.*$)" . "*.cpp,*.h" -g 1
カレントフォルダー内のC++言語ソースファイル内のコメント行を検索します。
.REMARKS
実験的に .docx/.pptx/.xlsx/.xlsm 形式のファイルにも対応しています。更に本スクリプト
の設置フォルダー内に itextsharp.dll が存在する場合はPDFファイルの検索も可能です
(ラスタ化された文字列やEXCELの数値・日付を除く)。
#>
param (
[String]$Pattern,
[String]$Dir,
[String]$Include = "*",
[ValidateSet("", "Unknown", "String", "Unicode", "Byte", "BigEndianUnicode", `
"UTF8", "UTF7", "UTF32", "Ascii", "Default", "Oem", "BigEndianUTF32")]
[Alias("e")][String]$Encoding = "Default",
[Alias("x")][String]$Exclude = "",
[Alias("g")][String]$Group = "0",
[Alias("h")][Switch]$HtmlOutput,
[Alias("i")][Switch]$IgnoreCase,
[Alias("n")][Switch]$Narrow,
[Alias("r")][Switch]$Recurse,
[Alias("s")][Switch]$SimpleMatch,
[Alias("bc")][ConsoleColor]$BackgroundColor = "Blue",
[Alias("cc")][ConsoleColor]$CapturegroupColor = "Red",
[Alias("fc")][ConsoleColor]$ForegroundColor = "White"
)
############ Edit Here ############
$BinaryFiles = "*.exe, *.dll, *.lnk, *.zip, *.bmp, *.gif, *.jpg, *.png"
$HtmlFile = "$($script:PSScriptRoot)\RegExS_Output.htm"
# $HtmlFile = "$($script:PSScriptRoot)\RegExS_Output_$((Get-Date).ToString('yyyyMMddHHmm')).htm"
###################################
if (-not $Pattern) { Write-Host "Pattern の指定がありません。" -Fore Red; Get-Help RegExS; return }
if (-not $Dir) { Write-Host "Dir の指定がありません。" -Fore Red; Get-Help RegExS; return }
$Dir = Convert-Path -LiteralPath $Dir
if (-not $Dir) { Write-Host "Dir は存在しません。" -Fore Red; Get-Help RegExS; return }
[Array]$IsContainer = Get-Item $Dir | %{ $_.PSIsContainer }
if ((-not $Recurse) -and $IsContainer.Length -eq 1 -and $IsContainer[0]) { $Dir += "\*" }
if ($SimpleMatch) {
$Pattern = [regex]::Escape($Pattern)
} else {
$Pattern = "(?m)" + $Pattern
}
if ($IgnoreCase) { $Pattern = "(?i)" + $Pattern }
if ($HtmlOutput) { HtmlHeader }
[String[]]$IncludeList = $Include -Split "," | %{ $_.Trim() }
[String[]]$ExcludeList = ($Exclude + "," + $BinaryFiles) -Split "," | %{ $_.Trim() } | ?{ $_ }
$global:ErrorView = "CategoryView"
if ($IncludeList.Length -eq 1) { # "-Filter" の方が "-Include" よりも速い
$files = Get-ChildItem $Dir -Filter $Include -Exclude $ExcludeList -Recurse:$Recurse -File
} else {
$files = Get-ChildItem $Dir -Include $IncludeList -Exclude $ExcludeList -Recurse:$Recurse -File
}
$global:ErrorView = "NormalView"
$ErrorActionPreference = "Stop"
trap [System.Exception] {
Write-Host "システム例外が発生しました。" -Fore Red
Write-Host $Error[0].ToString() $Error[0].InvocationInfo.PositionMessage
if ($HtmlOutput) {
HtmlFooter
try {
[Text.Encoding]::UTF8.GetBytes($script:Html.ToString()) | Set-Content -Path $HtmlFile -Encoding Byte # UTF-8N
[void]$script:Html.Clear()
} catch [System.Exception] {}
}
return
}
[Int]$Nmfile = 0
[Int]$Nmatch = 0
[Int]$Nmline = 0
[Int]$Nmchar = 0
if ($files) {
:LOOP foreach ($file in $files) {
Write-Debug "RegExS: $($file.FullName)"
try {
switch ($file.Extension) {
".docx" { $io = ReadDocxFile $file.FullName ; break }
".pptx" { $io = ReadPptxFile $file.FullName ; break }
".xlsm" { $io = ReadXlsxFile $file.FullName ; break }
".xlsx" { $io = ReadXlsxFile $file.FullName ; break }
".pdf" { $io = ReadPdfFile $file.FullName ; break }
Default {
$enc = GetEncodingFromBOM $file
if (-not $enc) {
if (IsBinary $file) {
Write-Host "バイナリ形式ファイル $($file.FullName) をスキップします。" -Fore Green
continue LOOP
}
$enc = $Encoding
}
$io = (Get-Content $file.FullName -Encoding $enc -Raw) -Replace "\r",""
}
}
} catch [System.UnauthorizedAccessException], `
[System.Management.Automation.ItemNotFoundException], `
[System.IO.IOException] {
Write-Host "$($Error[0].Exception.Message) 処理を継続します。" -Fore Red
if ($HtmlOutput) {
[void]$script:Html.Append("<span class=`"y`">$(Htmlify $Error[0].Exception.Message) 処理を継続します。</span>`n")
}
continue
}
if ($Narrow) {
Add-Type -AssemblyName "Microsoft.VisualBasic"
$io = [Microsoft.VisualBasic.Strings]::StrConv($io,[Microsoft.VisualBasic.VbStrConv]::Narrow)
$Pattern = [Microsoft.VisualBasic.Strings]::StrConv($Pattern,[Microsoft.VisualBasic.VbStrConv]::Narrow)
}
[Array]$Matches = Select-String -InputObject $io -Pattern $Pattern -CaseSensitive -AllMatches `
| %{ $_.Matches } | ?{ $_.Groups[$Group].Success }
if ($Matches) {
$Nmfile++
Write-Host $file.FullName -Fore Yellow
$bol = [Array](Select-String -InputObject $io -Pattern '(?m)^' -AllMatches | %{ $_.Matches } | %{ $_.Index }) `
+ ($io.Length + 1)
[Int]$nl = -1
if (-not $HtmlOutput) {
if ($Group -eq "0") {
for ([Int]$i=0; $i -lt $Matches.Length; $i++) {
$MatchIndex = $Matches[$i].Groups[0].Index
$MatchLength = $Matches[$i].Groups[0].Length
$MatchString = $Matches[$i].Groups[0].Value -Replace "`n","`n`t"
$NextMatch = $Matches[$i+1]
if ($bol[$nl+1] -le $MatchIndex) {
while ($bol[$nl+1] -le $MatchIndex) { $nl++ }
$index = $bol[$nl]
if ($index -ge $io.Length) { break }
$Nmline++
if ($file.Extension -eq ".xlsx" -or $file.Extension -eq ".xlsm") {
Write-Host $("{0,5}:" -F $script:cell[$nl]) -NoNewline
} else {
Write-Host $("{0,5}:" -F ($nl+1)) -NoNewline
}
}
$Nmatch++
if ($MatchLength -gt 0) {
$Nmchar += $MatchLength
Write-Host $io.SubString($index, $MatchIndex - $index) -NoNewline
Write-Host $MatchString -Back $BackgroundColor -Fore $ForegroundColor -NoNewline
$index = $MatchIndex + $MatchLength
while ($bol[$nl+1] -le $index) {
$nl++
$Nmline++
}
}
if ($NextMatch -and $NextMatch.Index -lt $bol[$nl+1]) { continue }
$eol = $bol[$nl+1] - 1
if ($eol -eq $io.Length) { $eol-- }
if ($io[$eol] -eq "`n") { $eol-- }
if ($index -le $eol) {
Write-Host $io.SubString($index, $eol+1 - $index)
} else {
Write-Host
}
}
} else {
for ([Int]$i=0; $i -lt $Matches.Length; $i++) {
$Match0Index = $Matches[$i].Groups[0].Index
$Match0Length = $Matches[$i].Groups[0].Length
$MatchIndex = $Matches[$i].Groups[$Group].Index
$MatchLength = $Matches[$i].Groups[$Group].Length
$MatchString = $Matches[$i].Groups[$Group].Value -Replace "`n","`n`t"
$NextMatch = $Matches[$i+1]
if ($bol[$nl+1] -le $Match0Index) {
while ($bol[$nl+1] -le $Match0Index) { $nl++ }
$index = $bol[$nl]
if ($index -ge $io.Length) { break }
$Nmline++
if ($file.Extension -eq ".xlsx" -or $file.Extension -eq ".xlsm") {
Write-Host $("{0,5}:" -F $script:cell[$nl]) -NoNewline
} else {
Write-Host $("{0,5}:" -F ($nl+1)) -NoNewline
}
}
$Nmatch++
if ($Match0Length -gt 0) {
$Nmchar += $MatchLength
Write-Host $io.SubString($index, $Match0Index - $index) -NoNewline
Write-Host $($io.SubString($Match0Index, $MatchIndex - $Match0Index) -Replace "`n","`n`t") `
-Back $BackgroundColor -Fore $ForegroundColor -NoNewline
Write-Host $MatchString -Back $BackgroundColor -Fore $CapturegroupColor -NoNewline
$index = $Match0Index + $Match0Length
$index0 = $MatchIndex + $MatchLength
Write-Host $($io.SubString($index0, $index - $index0) -Replace "`n","`n`t") `
-Back $BackgroundColor -Fore $ForegroundColor -NoNewline
while ($bol[$nl+1] -le $index) {
$nl++
$Nmline++
}
}
if ($NextMatch -and $NextMatch.Index -lt $bol[$nl+1]) { continue }
$eol = $bol[$nl+1] - 1
if ($eol -eq $io.Length) { $eol-- }
if ($io[$eol] -eq "`n") { $eol-- }
if ($index -le $eol) {
Write-Host $io.SubString($index, $eol+1 - $index)
} else {
Write-Host
}
}
}
} else {
[void]$script:Html.Append("<a href=`"file:///$($file.FullName)`" type=`"text`" class=`"y`">$($file.FullName)</a>`n")
if ($Group -eq "0") {
for ([Int]$i=0; $i -lt $Matches.Length; $i++) {
$MatchIndex = $Matches[$i].Groups[0].Index
$MatchLength = $Matches[$i].Groups[0].Length
$MatchString = $Matches[$i].Groups[0].Value -Replace "`n","`n`t"
$NextMatch = $Matches[$i+1]
if ($bol[$nl+1] -le $MatchIndex) {
while ($bol[$nl+1] -le $MatchIndex) { $nl++ }
$index = $bol[$nl]
if ($index -ge $io.Length) { break }
$Nmline++
if ($file.Extension -eq ".xlsx" -or $file.Extension -eq ".xlsm") {
[void]$script:Html.Append(("{0,5}:" -F $script:cell[$nl]))
} else {
[void]$script:Html.Append(("{0,5}:" -F ($nl+1)))
}
}
$Nmatch++
if ($MatchLength -gt 0) {
$Nmchar += $MatchLength
[void]$script:Html.Append($(Htmlify $io.SubString($index, $MatchIndex - $index)))
[void]$script:Html.Append("<span class=`"fc`">$(Htmlify $MatchString)</span>")
$index = $MatchIndex + $MatchLength
while ($bol[$nl+1] -le $index) {
$nl++
$Nmline++
}
}
if ($NextMatch -and $NextMatch.Index -lt $bol[$nl+1]) { continue }
$eol = $bol[$nl+1] - 1
if ($eol -eq $io.Length) { $eol-- }
if ($io[$eol] -eq "`n") { $eol-- }
if ($index -le $eol) {
[void]$script:Html.Append("$(Htmlify $io.SubString($index, $eol+1 - $index))`n")
} else {
[void]$script:Html.Append("`n")
}
}
} else {
for ([Int]$i=0; $i -lt $Matches.Length; $i++) {
$Match0Index = $Matches[$i].Groups[0].Index
$Match0Length = $Matches[$i].Groups[0].Length
$MatchIndex = $Matches[$i].Groups[$Group].Index
$MatchLength = $Matches[$i].Groups[$Group].Length
$MatchString = $Matches[$i].Groups[$Group].Value -Replace "`n","`n`t"
$NextMatch = $Matches[$i+1]
if ($bol[$nl+1] -le $Match0Index) {
while ($bol[$nl+1] -le $Match0Index) { $nl++ }
$index = $bol[$nl]
if ($index -ge $io.Length) { break }
$Nmline++
if ($file.Extension -eq ".xlsx" -or $file.Extension -eq ".xlsm") {
[void]$script:Html.Append(("{0,5}:" -F $script:cell[$nl]))
} else {
[void]$script:Html.Append(("{0,5}:" -F ($nl+1)))
}
}
$Nmatch++
if ($Match0Length -gt 0) {
$Nmchar += $MatchLength
[void]$script:Html.Append((Htmlify $io.SubString($index, $Match0Index - $index)))
[void]$script:Html.Append("<span class=`"fc`">$(Htmlify $io.SubString($Match0Index, $MatchIndex - $Match0Index))</span>")
[void]$script:Html.Append("<span class=`"cc`">$(Htmlify $MatchString)</span>")
$index = $Match0Index + $Match0Length
$index0 = $MatchIndex + $MatchLength
[void]$script:Html.Append("<span class=`"fc`">$(Htmlify $io.SubString($index0, $index - $index0))</span>")
while ($bol[$nl+1] -le $index) {
$nl++
$Nmline++
}
}
if ($NextMatch -and $NextMatch.Index -lt $bol[$nl+1]) { continue }
$eol = $bol[$nl+1] - 1
if ($eol -eq $io.Length) { $eol-- }
if ($io[$eol] -eq "`n") { $eol-- }
if ($index -le $eol) {
[void]$script:Html.Append("$(Htmlify $io.SubString($index, $eol+1 - $index))`n")
} else {
[void]$script:Html.Append("`n")
}
}
}
}
}
if ($file.Extension -eq ".xlsx" -or $file.Extension -eq ".xlsm") {
$script:cell.Clear()
}
}
}
Write-Host "$Nmfile ファイル、$Nmline 行、$Nmatch 件、$Nmchar 文字の一致がありました。" -Fore Green
if ($HtmlOutput) {
[void]$script:Html.Append("<span class=`"g`">$Nmfile ファイル、$Nmline 行、$Nmatch 件、$Nmchar 文字の一致がありました。</span>`n")
HtmlFooter
try {
[Text.Encoding]::UTF8.GetBytes($script:Html.ToString()) | Set-Content -Path $HtmlFile -Encoding Byte # UTF-8N
[void]$script:Html.Clear()
Write-Host "$HtmlFile に結果を出力しました。" -Fore Green
Start-Process -FilePath "file:///$HtmlFile"
} catch [System.Exception] {
Write-Host "Htmlファイルの出力に失敗しました。" -Fore Red
Write-Host $Error[0].Exception.Message
}
}
}
Function IsBinary($File) {
if ($File.Length -lt 2) { return $False }
if ($File.Length -gt 20000000) { return $True }
$bytes = Get-Content $File.FullName -ReadCount 4096 -TotalCount 4096 -Encoding Byte
[Int]$Nbo=0
[Int]$Nbe=0
[Int]$Nzo=0
[Int]$Nze=0
for ([Int]$i=0; $i -lt $bytes.Length; $i+=2) {
$Nbo++
if ($bytes[$i] -eq 0) { $Nzo++ }
}
for ([Int]$i=1; $i -lt $bytes.Length; $i+=2) {
$Nbe++
if ($bytes[$i] -eq 0) { $Nze++ }
}
if (($Nzo+$Nze -gt 0) -and ([System.Math]::Abs($Nzo/$Nbo-$Nze/$Nbe)/($Nbo+$Nbe) -lt 0.1)) { return $True }
Write-Debug "IsBinary: $($file.Name) $($Nzo+$Nze), $([System.Math]::Abs($Nzo/$Nbo-$Nze/$Nbe)/($Nbo+$Nbe))"
return $False
}
Function GetEncodingFromBOM($File) {
$bytes = Get-Content $File.FullName -ReadCount 4 -TotalCount 4 -Encoding Byte
$string = ($bytes | %{ "{0:X2}" -F $_ }) -Join ""
switch -Regex ($string) {
"^EFBBBF" { $enc="UTF8" ; break }
"^FFFE0000" { $enc="UTF32" ; break }
"^FFFE" { $enc="Unicode" ; break }
"^0000FEFF" { $enc="BigEndianUTF32" ; break }
"^FEFF" { $enc="BigEndianUnicode" ; break }
"^2B2F76(38|39|2B|2F)" { $enc="UTF7" ; break }
Default { $enc="" }
}
Write-Debug "GetEncodingFromBOM: $($File.Name) $($string) $($enc)"
return $enc
}
Function ReadDocxFile($DocxFile) {
Add-Type -AssemblyName WindowsBase
$file = (Get-Childitem -Path $DocxFile).FullName
$package = [System.IO.Packaging.Package]::Open($file, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
$parts = $package.GetParts() | %{ $_ }
$document = $parts | ?{ $_.Uri.OriginalString -eq "/word/document.xml" }
$footnotes = $parts | ?{ $_.Uri.OriginalString -eq "/word/footnotes.xml" }
$endnotes = $parts | ?{ $_.Uri.OriginalString -eq "/word/endnotes.xml" }
$comments = $parts | ?{ $_.Uri.OriginalString -eq "/word/comments.xml" }
$enc = [System.Text.Encoding]::UTF8
$sr = New-Object System.IO.StreamReader $document.GetStream(),$enc
$text = New-Object System.Text.StringBuilder
[void]$text.Append($sr.ReadToEnd())
$sr.Close()
if ($footnotes) {
$sr = New-Object System.IO.StreamReader $footnotes.GetStream(),$enc
[void]$text.Append($sr.ReadToEnd())
$sr.Close()
}
if ($endnotes) {
$sr = New-Object System.IO.StreamReader $endnotes.GetStream(),$enc
[void]$text.Append($sr.ReadToEnd())
$sr.Close()
}
if ($comments) {
$sr = New-Object System.IO.StreamReader $comments.GetStream(),$enc
[void]$text.Append("</w:r></w:p>" + $sr.ReadToEnd())
$sr.Close()
}
$package.Close()
$t = $text.ToString()
[void]$text.Clear()
$t = $t -Replace "\r?\n",""
$t = $t -Replace "</w:r></w:p></w:tc><w:tc>"," "
$t = $t -Replace "\s+"," "
$t = $t -Replace "</w:r></w:p>","`n"
$t = $t -Replace "<[^>]+>",""
$t = $t -Replace "&","&"
$t = $t -Replace "<","<"
$t = $t -Replace ">",">"
$t = $t -Replace "(?m)^ ?\r?\n",""
return $t
}
Function ReadPptxFile($PptxFile) {
Add-Type -AssemblyName WindowsBase
$file = (Get-Childitem -Path $PptxFile).FullName
$package = [System.IO.Packaging.Package]::Open($file, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
$parts = $package.GetParts() | %{ $_ }
$enc = [System.Text.Encoding]::UTF8
$text = New-Object System.Text.StringBuilder
for ([Int]$i = 1; $i -le 999; $i++) {
$slide = $parts | ?{ $_.Uri.OriginalString -eq "/ppt/slides/slide$i.xml" }
if (-not $slide) { break }
$sr = New-Object System.IO.StreamReader $slide.GetStream(),$enc
$tmp = $sr.ReadToEnd()
$sr.Close()
$sliderels = $parts | ?{ $_.Uri.OriginalString -eq "/ppt/slides/_rels/slide$i.xml.rels" }
if ($sliderels) {
$sr = New-Object System.IO.StreamReader $sliderels.GetStream(),$enc
$rel = [xml]$sr.ReadToEnd() | %{ $_.Relationships.Relationship } | ?{ $_.Type -Match "notesSlide" }
$sr.Close()
if ($rel) {
$nfile = $([io.path]::GetFileName($rel.Target))
$note = $parts | ?{ $_.Uri.OriginalString -eq "/ppt/notesSlides/$nfile" }
$sr = New-Object System.IO.StreamReader $note.GetStream(),$enc
$tmp += " " + $sr.ReadToEnd()
$sr.Close()
}
}
$tmp = $tmp -Replace "\r?\n",""
$tmp = $tmp -Replace "\s+"," "
[void]$text.Append($tmp + "`n")
}
$package.Close()
$t = $text.ToString()
[void]$text.Clear()
$t = $t -Replace "<[^>]+>",""
$t = $t -Replace "&","&"
$t = $t -Replace "<","<"
$t = $t -Replace ">",">"
return $t
}
Function ReadXlsxFile($XlsxFile) {
Add-Type -AssemblyName WindowsBase
$enc = [System.Text.Encoding]::UTF8
$file = (Get-Childitem -Path $XlsxFile).FullName
$package = [System.IO.Packaging.Package]::Open($file, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
$parts = $package.GetParts() | %{ $_ }
$text = New-Object System.Text.StringBuilder
$script:Cell = New-Object 'System.Collections.Generic.List[System.String]' 100000
$sst = $parts | ?{ $_.Uri.OriginalString -eq "/xl/sharedStrings.xml" }
if ($sst) {
$strings = New-Object 'System.Collections.Generic.List[System.String]' 5000
$sr = New-Object System.IO.StreamReader $sst.GetStream(),$enc
$si = [xml]$sr.ReadToEnd() | %{ $_.sst.si }
foreach ($s in $si) {
if ($s.t -and $s.t.GetType().Name -eq "String") {
$tmp = $s.t
} elseif ($s.t."#text") {
$tmp = $s.t."#text"
} elseif ($s.r) {
$tmp = ""
foreach ($r in $s.r) {
if ($r.t -and $r.t.GetType().Name -eq "String") {
$tmp += $r.t
} elseif ($r.t."#text") {
$tmp += $r.t."#text"
}
}
}
$tmp = $tmp -Replace "\r?\n",""
$tmp = $tmp -Replace "\s+"," "
[void]$strings.Add($tmp)
}
$sr.Close()
}
for ([Int]$i = 1; $i -le 999; $i++) {
$sheet = $parts | ?{ $_.Uri.OriginalString -eq "/xl/worksheets/sheet$i.xml" }
if (-not $sheet) { break }
$sr = New-Object System.IO.StreamReader $sheet.GetStream(),$enc
$rows = [xml]$sr.ReadToEnd() | %{ $_.worksheet.sheetdata.row }
foreach ($row in $rows) {
foreach ($col in $row.c) {
switch ($col.t) {
"s" { [void]$text.Append($strings[$col.v] + "`n")
[void]$script:Cell.Add("S$($i.ToString())$($col.r)") }
"inlineStr" { if ($col.is.t -and $col.is.t.GetType().Name -eq "String") {
$tmp = $col.is.t
} elseif ($col.is.t."#text") {
$tmp = $col.is.t."#text"
} elseif ($col.is.r) {
$tmp = ""
foreach ($r in $col.is.r) {
if ($r.t -and $r.t.GetType().Name -eq "String") {
$tmp += $r.t
} elseif ($r.t."#text") {
$tmp += $r.t."#text"
}
}
}
$tmp = $tmp -Replace "\r?\n",""
$tmp = $tmp -Replace "\s+"," "
[void]$text.Append($tmp + "`n")
[void]$script:Cell.Add("S$($i.ToString())$($col.r)") }
}
}
}
$sr.Close()
}
if ($strings) { $strings.Clear() }
$NumSheets = ($parts | %{ $_.Uri.OriginalString -Match "/xl/worksheets/sheet[0-9]+.xml" }).Length
for ([Int]$i = 1; $i -le $NumSheets; $i++) {
$sheetrels = $parts | ?{ $_.Uri.OriginalString -eq "/xl/worksheets/_rels/sheet$i.xml.rels" }
if (-not $sheetrels) { continue }
$sr = New-Object System.IO.StreamReader $sheetrels.GetStream(),$enc
$rel = [xml]$sr.ReadToEnd() | %{ $_.Relationships.Relationship } | ?{ $_.Type -Match "comments" }
$sr.Close()
if (-not $rel) { continue }
$cfile = $([io.path]::GetFileName($rel.Target))
$comment = $parts | ?{ $_.Uri.OriginalString -eq "/xl/$cfile" }
$sr = New-Object System.IO.StreamReader $comment.GetStream(),$enc
$cc = [xml]$sr.ReadToEnd() | %{ $_.comments.commentList.comment }
foreach ($c in $cc) {
$tmp = ""
foreach ($r in $c.text.r) {
if ($r.t -and $r.t.GetType().Name -eq "String") {
$tmp += $r.t
} elseif ($r.t."#text") {
$tmp += $r.t."#text"
}
}
$tmp = $tmp -Replace "\r?\n",""
$tmp = $tmp -Replace "\s+"," "
[void]$text.Append($tmp + "`n")
[void]$script:Cell.Add("S$($i.ToString())$($c.ref)C")
}
$sr.Close()
}
$package.Close()
$t = $text.ToString()
[void]$text.Clear()
return $t
}
Function ReadPdfFile($PdfFile) {
if (-not (Test-Path $script:PSScriptRoot\itextsharp.dll)) {
Write-Host "isharptext.dllがないため $PdfFile の内容を検索できません。" -Fore Red
return
}
Add-Type -Path $script:PSScriptRoot\itextsharp.dll
$reader = New-Object iTextSharp.text.pdf.pdfreader -ArgumentList $PdfFile
$text = New-Object System.Text.StringBuilder
for ([Int]$i = 1; $i -le $reader.NumberOfPages; $i++) {
$strategy = New-Object iTextSharp.text.pdf.parser.SimpleTextExtractionStrategy
[void]$text.Append([iTextSharp.text.pdf.parser.PdfTextExtractor]::GetTextFromPage($reader, $i, $strategy))
remove-variable strategy
}
$reader.Close()
$t = $text.ToString()
[void]$text.Clear()
return $t
}
Function RGBColor([ConsoleColor]$Color) {
switch -Exact ($Color) {
"Black" { return "#000000" }
"DarkBlue" { return "#000080" }
"DarkGreen" { return "#008000" }
"DarkCyan" { return "#008080" }
"DarkRed" { return "#800000" }
"DarkMagenta" { return "#012456" }
"DarkYellow" { return "#EEEDF0" }
"Gray" { return "#C0C0C0" }
"DarkGray" { return "#808080" }
"Blue" { return "#0000FF" }
"Green" { return "#008000" }
"Cyan" { return "#00FFFF" }
"Red" { return "#FF0000" }
"Magenta" { return "#FF00FF" }
"Yellow" { return "#FFFF00" }
"White" { return "#FFFFFF" }
Default { return "" }
}
}
Function HtmlHeader() {
$script:Html = New-Object System.Text.StringBuilder
[void]$script:Html.Append("<!DOCTYPE html>`n")
[void]$script:Html.Append("<html lang=`"ja`">`n") # <- You may want to change this
[void]$script:Html.Append("<meta charset=`"UTF-8`">`n")
[void]$script:Html.Append("<head>`n")
[void]$script:Html.Append("<title>RegExS Output</title>`n")
[void]$script:Html.Append("<style type=`"text/css`">`n")
[void]$script:Html.Append("body {color:#ffffff; background-color:$(RGBColor("DarkMagenta"))}`n")
[void]$script:Html.Append("pre{white-space:pre-wrap}`n")
[void]$script:Html.Append(".fc {color:$(RGBColor($ForegroundColor)); background-color:$(RGBColor($BackgroundColor))}`n")
[void]$script:Html.Append(".cc {color:$(RGBColor($CapturegroupColor)); background-color:$(RGBColor($BackgroundColor))}`n")
[void]$script:Html.Append(".g {color:lime}`n")
[void]$script:Html.Append(".y {color:yellow}`n")
[void]$script:Html.Append("</style>`n")
[void]$script:Html.Append("</head>`n<body>`n<pre>`n")
}
Function HtmlFooter() {
[void]$script:Html.Append("</pre>`n</body>`n</html>")
}
Function Htmlify($t) {
$t = $t -Replace "&", "&"
$t = $t -Replace ">", ">"
$t = $t -Replace "<", "<"
$t = $t -Replace """", """
return $t
}
Function Pause_and_Exit() {
Write-Host "終了するには何かキーを押してください . . ." -Fore Green
$Host.UI.RawUI.FlushInputBuffer()
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") | Out-Null
exit
}
Function Main() {
if ($DoubleClicked) { $Interactive = $True }
if ($Interactive) {
if ($Pattern) {
Write-Host "検索対象の正規表現を入力してください。[$Pattern]:" -NoNewline -Fore Green
$Answer = ""
try { $Answer = Read-Host } catch [System.Exception] {}
if ($Answer) { $Pattern = $Answer }
} else {
Write-Host "検索対象の正規表現を入力してください。:" -NoNewline -Fore Green
try { $Pattern = Read-Host } catch [System.Exception] {}
if (-not $Pattern) { Pause_and_Exit }
}
Write-Host "キャプチャグループ(名前/番号)を指定してください。[$Group]:" -NoNewline -Fore Green
$Answer = ""
try { $Answer = (Read-Host).Trim() } catch [System.Exception] {}
if ($Answer) { $Group = $Answer }
Write-Host "検索対象のフォルダーを指定してください。" -Fore Green
Add-Type -AssemblyName System.Windows.Forms
$fbd = New-Object System.Windows.Forms.FolderBrowserDialog
$fbd.ShowNewFolderButton = $false
$fbd.Description = "検索対象のフォルダーを指定してください。"
if ($Dir -and (Test-Path -LiteralPath $Dir)) {
$fbd.SelectedPath = Convert-Path -LiteralPath $Dir
} else {
$fbd.SelectedPath = [string]$PWD
}
$Result = $fbd.ShowDialog((New-Object System.Windows.Forms.Form -Property @{TopMost = $true}))
if ($Result -eq [System.Windows.Forms.DialogResult]::OK) {
$Dir = $fbd.SelectedPath
} else {
Write-Host "入力値が不正です" -Fore Red; Pause_and_Exit
}
$fbd.Dispose()
#Begin Get-WindowFocus
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class SFW {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
"@
$PPID=$PID
For ([Int]$i=0; $i -lt 2; $i++) {
$PPID=(Get-WmiObject Win32_Process -Filter "ProcessID=$PPID").ParentProcessID
try {
$WindowTitle = (Get-Process -ID $PPID -ErrorAction SilentlyContinue).MainWindowTitle
$WindowHandle = (Get-Process -ID $PPID -ErrorAction SilentlyContinue).MainWindowHandle
if ($WindowTitle) {
[void][SFW]::SetForegroundWindow($WindowHandle)
break
}
} catch [System.Exception] { break }
}
#End Get-WindowFocus
Write-Host "サブフォルダーを検索に含めますか。Y/N [$(if($Recurse){"Y"}else{"N"})]:" -NoNewline -Fore Green
try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {}
switch ($Answer) {
"Y" { $Recurse = $True }
"N" { $Recurse = $False }
"" { }
default { Write-Host "入力値が不正です" -Fore Red; Pause_and_Exit }
}
Write-Host "対象ファイル名を入力してください(ワイルドカード使用可)。[$Include]:" -NoNewline -Fore Green
$Answer = ""
try { $Answer = (Read-Host).Trim() } catch [System.Exception] {}
if ($Answer) { $Include = $Answer }
Write-Host "その他のオプションを指定しますか。Y/N [N]:" -NoNewline -Fore Green
$Answer = ""
try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {}
if ($Answer -eq "Y") {
Write-Host "Htmlファイルを出力しまますか。Y/N [$(if($HtmlOutput){"Y"}else{"N"})]:" -NoNewline -Fore Green
try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {}
switch ($Answer) {
"Y" { $HtmlOutput = $True }
"N" { $HtmlOutput = $False }
"" { }
default { Write-Host "入力値が不正です" -Fore Red; Pause_and_Exit }
}
Write-Host "単純文字列検索を有効にしますか。Y/N [$(if($SimpleMatch){"Y"}else{"N"})]:" -NoNewline -Fore Green
try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {}
switch ($Answer) {
"Y" { $SimpleMatch = $True }
"N" { $SimpleMatch = $False }
"" { }
default { Write-Host "入力値が不正です" -Fore Red; Pause_and_Exit }
}
Write-Host "大小文字を区別しないようにしますか。Y/N [$(if($IgnoreCase){"Y"}else{"N"})]:" -NoNewline -Fore Green
try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {}
switch ($Answer) {
"Y" { $IgnoreCase = $True }
"N" { $IgnoreCase = $False }
"" { }
default { Write-Host "入力値が不正です" -Fore Red; Pause_and_Exit }
}
Write-Host "検索前に全角文字を半角文字に変換しますか。Y/N [$(if($Narrow){"Y"}else{"N"})]:" -NoNewline -Fore Green
try { $Answer = (Read-Host).Trim().ToUpper() } catch [System.Exception] {}
switch ($Answer) {
"Y" { $Narrow = $True }
"N" { $Narrow = $False }
"" { }
default { Write-Host "入力値が不正です" -Fore Red; Pause_and_Exit }
}
Write-Host "除外ファイル名を入力してください(ワイルドカード使用可)。[$Exclude]:" -NoNewline -Fore Green
$Answer = ""
try { $Answer = (Read-Host).Trim() } catch [System.Exception] {}
if ($Answer) { $Exclude = $Answer }
Write-Host "Byte Order Markの無いファイルの文字コード種別を入力してください。[$Encoding]:" -NoNewline -Fore Green
$Answer = ""
try { $Answer = (Read-Host).Trim() } catch [System.Exception] {}
if ($Answer) {
$Encoding = $Answer
$EncodingList = @("unkown", "string", "unicode", "byte", "bigendianunicode", `
"utf8", "utf7", "utf32", "ascii", "default", "oem", "bigendianutf32")
if (-not ($EncodingList -Contains $Encoding.ToLower())) {
Write-Host "入力値が不正です" -Fore Red; Pause_and_Exit
}
}
} elseif ($Answer -ne "N" -and $Answer -ne "") {
Write-Host "入力値が不正です" -Fore Red; Pause_and_Exit
}
}
RegExS $Pattern $Dir $Include -e $Encoding -g $Group -h:$HtmlOutput -i:$IgnoreCase -n:$Narrow -r:$Recurse `
-s:$SimpleMatch -x $Exclude `
-bc $BackgroundColor -cc $CapturegroupColor -fc $ForegroundColor
if ($Interactive) { Pause_and_Exit }
}
Main