環境は、WSL2 Ubuntu-22.04 です。
WSL で xyz
と入力し、そのあと、Backspace で、xyz
を消して、abc
と入力します。
結果は以下のようになります。
Bash
1$ script 2Script started, output log file is 'typescript'. 3$ echo abc 4abc 5$ exit 6exit 7Script done. 8$ cat -v typescript 9Script started on 2023-12-16 15:06:46+09:00 [TERM="xterm-256color" TTY="/dev/pts/4" COLUMNS="144" LINES="18"] 10^[[?2004h^[]0;user@HostName: ~^G^[[01;32muser@HostName^[[00m:^[[01;34m~^[[00m$ echo xyz^H^[[K^H^[[K^H^[[Kabc^M 11^[[?2004l^Mabc^M 12^[[?2004h^[]0;user@HostName: ~^G^[[01;32muser@HostName^[[00m:^[[01;34m~^[[00m$ exit^M 13^[[?2004l^Mexit^M
結果は、echo xyz^H^[[K^H^[[K^H^[[Kabc^M
で、xyz^H^[[K^H^[[K^H^[[K
の部分を削除したいです。
WSL2 だと、^[[K
が入るので、ひとまずそれらを削除して、xyx^H^H^Habc^M
にしてから、col -b
とすると以下の結果になります。
Bash
1$ sed $'s/\e\[K//g' typescript | col -b | cat -v 2# 不要な部分省略 3echo abc
うまくいっているように見えます。ところが、WSL だと、abc
と入力し、そのあと左矢印「←」で三回カーソルを移動し、
それから右矢印「→」で三回カーソルを移動させると、次のようにログが記憶されます。
echo abc^H^H^H^[[C^[[C^[[C^M
なので、この状態で、col -b
とすると、カーソルを移動しただけなのに、abc
が消えてしまいます。
Bash
1$ col -b < typescript 2echo CCC
そこで、col -b
を使わずに、バックスペースの制御文字と消したはずの文字列をファイルに残さずに削除したいと思っています。
バックスペースの制御文字だけ消すなら、
sed -E $'s/(\b\e\[K)+//g' typescript | cat -v
でいいようですが、
バックススペースで消したはずの文字列も削除しようとするとそう簡単にはうまくいきません。
いろいろとテストしてみると、^[[K
以外のパターンが入る場合もあり、ちょっと私個人の力では手に負えない印象です。
そこで、日本語とか違うパターンとかは無視して、今回は簡略化して、^[[K
が交じるパターンのみで確認したいと思っています。
例として以下のようなものです。
echo xyz^H^[[K^H^[[K^H^[[Kabc1234^H^[[K^H^[[K77^H^H^H^[[C^[[C^[[Cxy^H^[[K^H^[[Kpq^M
echo abc1277pq
としたのですが、Backspace で何度か適当に削除したり、カーソル移動したりしたものがログに保存されているとします。
考え方としては、一行ずつ頭から ^H^[[K
を一単位として、それが繰り返されている分だけ、その前の一文字を繰り返して消せばいいのではないか、と思っています。
なので、上の例だと、sed -E $'s/.{3}(\b\e\[K){3}//'
で、xyz
と制御文字を、
次にsed -E $'s/.{2}(\b\e\[K){2}//'
で、34
と制御文字を、その次にsed -E s/.{2}(\b\e\[K){2}//
で、xy
と制御文字を消して、
最後に不要な移動カーソルの ^H
や ^[[C
を削除すればいいかと。
そのように考えて以下のように書いてみました。
Bash
1#!/bin/bash 2while read line; do 3 if [[ $line =~ $'\b\e[K' ]]; then 4 n1=$(echo "$line" | grep -oE $'(\b\e\[K)+' | grep -cE $'(\b\e\[K)+') 5 for ((i=1; i<=n1; i++)); { 6 if [[ $line =~ (($'\b\e[K')+) ]]; then 7 n2=$(echo -n ${BASH_REMATCH[1]} | sed $'s/\b\e\[K/@/g' | wc -m) 8 # 以下のコードでは、\b\e\[K ではうまくいかず、16進法で表記したらうまくいった 9 line=$(echo "$line" | sed -E $'s/.{'$n2'}(\x08\x1b\[K){'$n2'}//') 10 fi 11 } 12 echo "$line" | tr -d $'\b\e[C' 13 else 14 echo "$line" | tr -d $'\b\e[C' 15 fi 16done < typescript > test.log
結果を見ると、一応想定通りのように見えます。
この考え方やコードで間違ったところはないでしょうか?
ご存じの方いらしたらよろしくお願いします。
Bash
1$ cat -v test.log 2Script done on 2023-12-16 16:54:30+09:00 [COMMAND_EXIT_CODE="0"] 3Script started on 2023-12-16 17:41:51+09:00 [TERM="xterm-256color" TTY="/dev/pts/4" COLUMNS="144" LINES="18"] 4?2004h]0;user@HostName: ~^G01;32muser@HostName00m:01;34m~00m$ echo abc1277pq^M 5^[[?2004l^Mabc1277pq^M 6?2004h]0;user@HostName: ~^G01;32muser@HostName00m:01;34m~00m$ exit^M 7^[[?2004l^Mexit^M 8 9Script done on 2023-12-16 17:43:17+09:00 [COMMAND_EXIT_CODE="0"]
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2023/12/17 01:02