手撸shell search

138 阅读3分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第n篇文章,点击查看活动详情

背景

一个普通的早晨, 我突然回忆起几个月前写的代码段,但忘记写在哪个文件里面了,这时我拿起 everything, fd 一看, 哦嚯,只能搜文件,简单打开几个文件看了下,并没有找到我想要的内容。这时,我就一拍脑袋,热了。。整个命令搜索搞定它,于是有了此搜索工具

具体代码

function search ($searchKey) {
  $target = "E:\git\md-set"
  cd $target
  $script:count = 0function searchDirectory ($searchKey) {
  $files = get-childItem *.md && Get-ChildItem -Directory
  for ($i = 0; $i -lt $files.Count; $i++) {
    if(Test-Path $files[$i] -PathType Container) {
      Set-Location $files[$i]
      return searchDirectory($searchKey)
    } else {
      $current = $files[$i]
      $targetContext = Get-Content $current | Select-String -Pattern $searchKey -CaseSensitive -SimpleMatch
      if($targetContext.Length) {
        Write-Host $targetContext
        Write-Host "内容位于: $current"
        $script:count++
      }
    }
  }
}
​
Measure-Command -Expression {
  searchDirectory($searchKey)
} | Select-Object -Property TotalMilliseconds
​
  cd $target
  Write-Host "有 $count 个结果"
}

调用效果如下

c.png

github地址

github.com/nowdothat/g…

踩坑之旅

函数调用也许不需要()

powershell 跟 javascript 函数调用不同的是,如果你的函数没有参数,就不需要用()..这个特性挺奇葩的

获取所有目标文件并深度递归

Get-ChildItem
   [[-Path] <string[]>]
   [[-Filter] <string>]
   [-Include <string[]>]
   [-Exclude <string[]>]
   [-Recurse]
   [-Depth <uint32>]
   [-Force]
   [-Name]
   [-Attributes <FlagsExpression[FileAttributes]>]
   [-FollowSymlink]
   [-Directory]
   [-File]
   [-Hidden]
   [-ReadOnly]
   [-System]
   [<CommonParameters>]

目标语法:Get-ChildItem -Recurse, 但是真这样做也不行,感觉有点那啥,于是用程序设计去解决它: 判断目录,再递归处理

get-childItem *.md && Get-ChildItem -Directory

作用域

变量作用域是 powershell的一大坑点,但从大局来考虑确实需要,但不管怎样,对开发者确实不又好,少不了又要去翻文档:

PowerShell 范围

PowerShell 支持以下范围:

  • 全局:PowerShell 启动时或创建新会话或运行空间时生效的范围。 在全局范围内创建 PowerShell 时存在的变量和函数,例如自动变量和首选项变量。 PowerShell 配置文件中的变量、别名和函数也在全局范围内创建。 全局范围是会话中的根父范围。
  • 本地:当前范围。 本地范围可以是全局范围或任何其他范围。
  • 脚本:脚本文件运行时创建的作用域。 只有脚本中的命令在脚本范围内运行。 对于脚本中的命令,脚本范围是本地范围。

范围修饰符

变量、别名或函数名称可以包含以下任一可选作用域修饰符:

  • global: - 指定名称存在于 全局 范围内。

  • local: - 指定 名称存在于本地 范围内。 当前范围始终是 本地 范围。

  • private: - 指定名称为 Private ,并且仅对当前作用域可见。

    备注

    private 不是作用域。 这是 一个选项 ,用于更改定义项的范围之外的项的可见性。

  • script: - 指定 脚本 范围中存在名称。 脚本 范围是最近的上级脚本文件的范围,如果没有最近的上级脚本文件,则为 Global

  • using: - 用于通过 cmdlet(如 Start-JobInvoke-Command)运行脚本时访问另一个作用域中定义的变量。

  • workflow: - 指定工作流中存在名称。 注意:PowerShell v6 及更高版本不支持工作流。

  • `` - PowerShell PSDrive 提供程序创建的修饰符。 例如:

    命名空间说明
    Alias:在当前作用域中定义的别名
    Env:在当前范围内定义的环境变量
    Function:在当前作用域中定义的函数
    Variable:在当前作用域中定义的变量

脚本的默认范围是脚本范围。 函数和别名的默认范围是本地范围,即使它们在脚本中定义也是如此。

所以要想使用 count去统计,必须使用count 去统计,必须使用 script 去修饰

时间统计

Measure-Command -Expression { } 这个挺好,配合 对象选择,体验最好的一次。。

完结体验

这次折腾起码解决了搜索问题,但还有优化空间,后续有空会考虑继续优化。

从代码体验上来说,powershell 语法大部分是符合直觉的,但函数调用,作用域这两块还是令人不满意,希望继续加油,不要让zx 超越了