PowerShell 6.2实现grep-like功能

环境

操作系统Win10 1909,PowerShell版本($PSVersionTable.PSVersion.ToString())6.2.3。$PSCulture$PSUICulture这回都是ja-JP,放心好了。暂且用自带的终端。

缘由

之前在现场工作时,由于实在没有称手的工具,Visual Studio又没办法续许可,想用grep的话,只好用sakura之类的文本编辑器,非常难受。于是我摸了四个月的鱼,用PowerShell 5.1做了一个ww

但是后来退场了,脚本拿不走,只好重写一个。这次只花了一天时间www

代码

D:\work\util\simpleFind.ps1

[CmdletBinding()]
param (
    [Parameter(ValueFromPipeline)]
    [Object]
    $Path = '.',
    [Parameter()]
    [string]
    $PathFilter = '.*\.(cs|cshtml|css|js|json)$',
    [Parameter()]
    [Object]
    $Encoding = 'UTF8',
    [Parameter(Mandatory)]
    [string]
    $Pattern,
    [Parameter()]
    [switch]
    $FindLines
)

begin {
    # file counter
    $Script:fileCounter = [UInt32]0;
    if ($FindLines) {
        # found counter
        $Script:lineCounter = [UInt32]0;
    }

    function findLine {
        param (
            [Microsoft.PowerShell.Commands.GroupInfo]$resultGroup
        )
        foreach ($result in $resultGroup.Group) {
            # line
            $Script:lineCounter += [UInt32]1;
            Write-Host (" {0,5} " -f $result.LineNumber) `
                -ForegroundColor White `
                -BackgroundColor DarkBlue `
                -NoNewline;
            Write-Host $result.Line.Trim();
        }
    }
}

process {
    Set-Variable -Name 'files' -Value {
        if ($Path -is [string] -and (Test-Path $Path)) {
            # when it's a path string
            return Get-ChildItem -Path $Path -Recurse; 
        } elseif ($Path -is [System.IO.FileInfo]) {
            # when it's a file
            return $Path;
        } else {
            # when it's a directory or etc.
            return $null;
        }
    }.InvokeReturnAsIs();
    # avoid wasteful process
    if ($null -eq $files) {
        return;
    }
    # main part
    Set-Variable -Name 'resultSet' -Value ($files |
            Where-Object Name -Match $PathFilter |
            Select-String -Encoding $Encoding -AllMatches $Pattern |
            Select-Object -Property Path, LineNumber, Line |
            Sort-Object -Property Path, LineNumber);
    # when found
    if ($null -ne $resultSet) {
        Set-Variable -Name 'resultGroupSet' -Value ($resultSet |
                Group-Object -Property Path);
        foreach ($resultGroup in $resultGroupSet) {
            # file path
            $Script:fileCounter += [UInt32]1;
            Write-Host $resultGroup.Name `
                -ForegroundColor White `
                -BackgroundColor DarkBlue;
            if ($FindLines) {
                findLine($resultGroup);
            }
        }
    }
}

end {
    Write-Host ("{0} file(s) found" -f $Script:fileCounter);
    if ($FindLines) {
        Write-Host ("{0} line(s) found" -f $Script:lineCounter);
    }
}

用例

前提:在预先加载的$PROFILE里写了这些:

New-PSDrive `
    -Name 'W' `
    -PSProvider FileSystem `
    -Root 'D:\work';

临时装载了一个驱动器。

要查的项目是这个:W:\prj\HelloMVC\

# find which files have "information"
W:\util\simpleFind.ps1 -Path 'W:\prj\HelloMVC\' -Pattern 'information'
# same as ahead. using pipeline
'W:\prj\HelloMVC\' | W:\util\simpleFind.ps1 -Pattern 'information'
# also using pipeline. just like what we usually do 
Get-ChildItem 'W:\prj\HelloMVC\' -Recurse | W:\util\simpleFind.ps1 -Pattern 'information'
# find files and lines
W:\util\simpleFind.ps1 -Path 'W:\prj\HelloMVC\' -Pattern 'information' -FindLines

后记

没什么好说的。告别上一个现场,为之后的工作和生活做准备就是了。

InSb

InSb

只是跟工作和生活相关的记录