LoginSignup
0
0

More than 1 year has passed since last update.

PowerShell上で実行するCLIアプリケーションでのエスケープ文字

Posted at

なんで気になった?

私はgoで作成していたCLIアプリケーションを時々微改修していたのですが、ふと思い立って、多数のファイルを逐次処理する箇所にプログレスバーを表示しようとしていました。コマンドライン上でプログレスバーを更新するとなった時、簡単かつ正攻法である方法といえば、既にプログレスバーが表示されている行で、キャリッジリターンで行頭に飛び、全て上書きするというものが挙げられると思います。
普段私はそのアプリケーションをPowerShell上で動かしており、それに対応できる、最悪それだけには対応していれば良いという方針で方法を探っていました。
その中で、 PowerShellでは、キャリッジリターンは`rで表現する という文を見つけました。PowerShell内で試してみたところ、実際そのようだと思わえました。

Write-Host "ab`rc" # Output: cb

なので……

func processFiles(fileNames []string) {
  fileNum := len(fileNames)// ファイル数は2000とかそのくらいです
  d := int(float64(fileNumber) / 100)
  for index, fileName := range fileNames {
    // ファイル処理
    if (index+1) % 100 == 0 {
      fmt.Print("`r") // PowerShell専用対応

      astCount := int((index+1) / 100)
      barCount := d - astCount
      fmt.Print(strings.Repeat("*", astCount))
      fmt.Print(strings.Repeat("-", barCount))
      fmt.Printf(
        "[%d/%d done.]",
        index + 1,
        fileNum
      )
    }
  }
}

 
 

      fmt.Print("`r") // PowerShell専用対応

 
 
 
 
 

      fmt.Print("`r") // 元凶

 
 
 
 
 

どんどん伸びるプログレスバーになるはずだったもの

まあ、コンソールが中々のことになりました。

*--------[100/1000 done.]`r**--------[200/1000 done.]`r***-------[300/1000 done.]`r
...

実際はもっと酷かったです。

実際どうするべきだったか

一回頭がリセットされた後で、原因を探ろうと考えました。
とりあえず、まずは同じくCLIアプリケーションを作成でき、その中でも速やかに作成できる部類に入るJavaScriptで同様の現象が起こるか確かめてみました。

test.js
console.log('ab`rc');
# PowerShell

node test.js

# 宗派によってはこちらでも
deno run test.js

# Output: ab`rc

どうも、PowerShell上で実行だからといって、PowerShellで文字列をecho なり Write-Host した時とは状況が異なるようです。

そういうことなので、他の手段を試してみました。

test.js
console.log('ab\rc');
# PowerShell
deno run test.js # 私の宗派はこっちです

# Output: cb

一発目でビンゴ。
という訳でgoでもサクッとテスト用のコードを書いて実行してみました。

test.go
package main

import (
	"fmt"
)

func main() {
	fmt.Println("ab\rc")
}

# PowerShell
go run test.go

# Output: cb

やったぜ。

おまけ

他のシェルで使えるキャリッジリターンの記法が使えるならば、他のものも試したくなってきます。

test.js
console.log('\u001b[31mThis is red text.\u001b[0m');
// Outputは赤文字
test.go
package main

import (
	"fmt"
)

func main() {
	fmt.Println("\u001b[31mThis is red text.\u001b[0m")
}

// Outputは赤文字

:thumbsup:

最後に

PowerShellの echo なり Write-Host`rを入れ込んだ時の挙動と、コンソールアプリケーションのコードで`rを標準出力させた時の挙動の差について、自分の中で納得する理屈が分からないのが現状です。
このあたりについて詳しい方がいらっしゃったら、コメントなどして頂けると有り難いです!

ここまで読んでくださり、ありがとうございます!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0