仿 Linux 的 Powershell 小工具--nl

10120 단어 linuxpowershel
Linxu 世界中有許多有趣的小工具, 剛好可以拿來當學習 Powershell 撰寫腳本檔的範例, 本篇就以 nl 為目標.

幫文字檔編行號的 nl



nl 是個可以幫文字檔編行號的小工具, 如果你需要將原始碼放到文件上, 那這個小工具就可以幫上你的忙, 最簡單用法尙像昣:

$ nl test.c
     1  #include <locale.h>
     2  #include <stdio.h>
     3  #include <wchar.h>

     4  int main() {
     5    char* loc = setlocale(LC_CTYPE, "C.UTF-8");

     6    printf("%s\n", loc);
     7    wchar_t str[] = L"扣人心弦CD";
     8    printf("total:%d bytes\n", sizeof(str));
     9    wprintf(L"%ls is %ld chars.", str, wcslen(str));
    10  }


預設的情況下它會以 6 位數從 1 開始編行號, 並且在行號後面空 2 格再顯示內容的如果你希望客製化輸的格式, 可仸使用式


參數名稱
可能值
설명


-에스
字串
行號與內文間的分隔字串, 預設就是 ""

-V
數值
起始行號, 預設從 1 開始

-w
數值
行號寬度,預設為 6

-N
字串
對齊格式:rn:靠右對齊rz:靠右對齊, 開頭補 0ln:靠左對齊


上表並未列出所有的選項, 有興趣可自行參考, 下一節 Powershell 的實作也僅以上述參數為準.

Powershell 的簡易實作



에서 Powershell 版本的時候, 我們盡量簡化內容, 這樣才符合小工具的稱呼.

參數的定義



以下是 Powershell 版本 nl 工具的參數定義:

param(
  [String]$path="",
  [int]$w=3,
  [Parameter(ValueFromPipeline=$true)][String]$line,
  [String]$s=" ",
  [ValidateScript({$_ -ge 0})][int]$v=1,
  [ValidateSet("ln","rn","rz")][String]$n="rn"
)



  • Powershell 的好處是可以直接用定義變數的方式定義命令行的 參數 , 它會幫你剖析命令行, 取出個別的參數轉換成正確的型別後設定給變數.因此, 如果這樣執行腳本檔:

    .\nl.ps1 -s "--"
    

    變數 $s 的內容就是 "--", 而且還可以直接設定預設值, 如果像是這樣執行腳本檔:

    .\ml.ps1
    

    那麼 $s 就會是預設的 "".

  • 參數定義時還可以指定 驗證方式 , 這裡我們使用了兩種驗證方式:

    [ValidateSet("ln","rn","rz")][String]$n="rn"
    

    這表示 -n 參數只能接受 "ln","rn","rz"其中的一種.

    [ValidateScript({$_ -ge 0})][int]$v=1
    

    這表示 -v 參數的值可由括號內的程式區塊來驗證, 這裡就是很簡單的確認參值是 0 或正整數.

  • 你也可以指定哪個參數可以接收從管線傳入的資料:

    [Parameter(ValueFromPipeline=$true)][String]$line
    

    這裡 line 可以接受從管線傳入的字串, 並且依序編行號後輸出.
  • 為了 為了 讓 這 個 小 小 工具 工具 符合 符合 符合 PowerShell 的 慣例, 採用 -path 指定 檔名 檔名 檔名, 由於 它 是 是 第一 個 參數, 所以 如果 執行 時 沒有 -path 參數, 剩餘 沒有 指定 指定 參數 到 到 到 到 對應 自動 自動 自動 自動 自動 會 會 就 參數 參數 參數 參數 參數 參數 參數 參數 參數 參數 參數 參數 參數 參數 個 第一 第一 第一 第一 第一 第一 第一 第一 第一 第一 第一. .

  • 處理檔名



    接著確認如果有指定要編號的檔案, 就將檔案內容讀入:

    begin{
      $contents = @()
      if(test-path $path) {
        $contents = get-content -path $path
      }
    }
    


    要注意的是, 因為我們的腳本檔可以接受從管線輸入的字串, 所以必須要採用 -path 程式區塊, begin/prcoess/endbegin 都只會執行一次, 但對於收到的每一個字串, 都會執行一次end .

    處理從管線收到的陣列



    에서 process 中將收到的資料添加到 process 陣列中:

    process{
      $contents += $line
    }
    


    格式化輸出



    最後 我們根據參數內容決定格式化的方式, 並使用 $contents 格式化運算器 幫我們編排內容:

    end{
      $w = [system.math]::max(
        $w,
        [system.math]::ceiling([system.math]::log($contents.length, 10))
      )
      $p = ""
      if($n -eq "rz"){$p = ":d$w"}
      if($n -eq "ln"){$w = -$w}
      for($i = 0;$i -lt $contents.length;$i++) {
        "{0,$w$p}$s{1}" -f ($v + $i),$contents[$i] 
      }
    }
    


  • 使用 使用 的 的 시스템 .math 中 的 函式 函式 來 計算 行號 寬度 寬度, 로그 與 Ceil 可以 幫 我們 我們 根據 行數 行數 算出 算出 最 最 小 小 的 行號 寬度, 再 -f 參數 指定 的 值取 值取 大者 為 準 準 1045791919101410
  • 根據 -w 設定 決定 決定 是否 要 要 加上 -n 格式化 運算器 中 中 可 在 數字 數字 左方補零 的 的 的 "d"格式, 以及 是否 要 要 將 負數 負數 負數 讓 數字 向 向 左對 齊... 1046791910
  • 最後就利用上述設定組成 -f 格式化運算器的格式字串, 編排出我們所需的內容
  • .

    좋은 웹페이지 즐겨찾기