要はこういうことをしたい。
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
↓
ghp_************************************
(これは GitHub の personal access token を例にしているが、このトークンはもう存在しない)
いくつか要求があり、
- 全部置き換えるとわかりづらいので、一部はそのまま残したい。↑でいうと
ghp_
の部分 - 他の部分を置き換える文字は決め打ちでいい。↑でいうと
*
でいい - ただし、文字数は置き換えの前後で同じ長さを維持したい
残したい文字列のパターンがあらかじめ分かってないとダメなので、汎用的な正規表現は書けなそう?今回は Authentication token format updates are generally available | GitHub Changelog に列挙されてるパターンだけカバーできればよかったので、↓こんな感じで解決した。
echo $pat | perl -pe 'print; s/([^_]*_)(.*)/$1 . "*" x length($2)/e'
きっと sed や awk でできるのだろうし、なんなら bash だけでできるのかもしれないが、GNU と BSD の違いとかで悩みたくなかったので Perl のワンライナーのお世話になった。
最終的にシェル関数を定義しておしまい。
pat-mask() { local pat if [ -p /dev/stdin ]; then pat=$(cat -) else pat=$1 fi echo $pat | perl -pe 'print; s/([^_]*_)(.*)/$1 . "*" x length($2)/e' }
当初は↓というのを編み出したが、これに至るまでに Use a variable-width lookbehind if it won’t match more than 255 characters – The Effective Perler というエラーにひっかかって結局そこそこ悩むハメになった((?<=[^_]*_)(.*)
みたいな正規表現を書いてて Lookbehind longer than 255 not implemented in regex に抵触した)
echo $pat | perl -pe 'print; s/(?<=_)(.*)/"*" x length($1)/e'