Ansatzの備忘録

勉強したことあるいはふと思い立ったこと

シェルワンライナー160本ノック問題3

問題3 ファイル名の一括変更

seq 10000000 | xargs -P2 touch

で1から100万までのファイルを作り、そのファイル名の先頭を0で埋める問題だった。 touch に関しては引数 FILE が存在しない場合、 -c または -h オプションが指定されない限り、 空ファイルが作成される仕様になっている。手も足も出なかった。正規表現の理解が求められている気がした。

解答例では rename コマンドを用いて

ls -U | xargs -P2 rename 's/^/0000000/;s/0*([0-9]{7})/$1/'

として答えを出していた。まず ls でフォルダ名を行ごとに出力し、それらを xargs に渡して rename の引数にしている。後ろの正規表現Perlにおける正規表現のルールに従っているらしい。rename の前半、s/^/0000000/ で先頭に7つゼロを付け加えている。^は行頭を表すとはどういうことなのかいまいちわかってなかったことを思い知らされた。rename の後半では、s/0*([0-9]{7})/$1/ で後ろ7桁の数字を抜き出している。このとき0*でゼロ個以上の0を表し、() 内については [0-9] で0から9の数字のいずれかを表し、それが7個あることを {7} で表している。そこから () で囲った部分を後方参照で残して0埋めされた数字を出力している。

 

sed のマニュアルを info sed | grep -C 3 'semicolon'  で出して読んでみると、

Commands within a SCRIPT or SCRIPT-FILE can be separated by
semicolons (';') or newlines (ASCII 10).

とあり、予想通りセミコロンでコマンドを区切れるとのことだった。grep でマニュアルの一部を切り抜いて読むことになれるとずいぶんと便利だ。ほかにも info sed | grep -C 6 'slash' で検索をかけると

The '/' characters may be uniformly replaced by any other single
character within any given 's' command.  The '/' character (or whatever
other character is used in its stead) can appear in the REGEXP or
REPLACEMENT only if it is preceded by a '\' character.

と書いてあり、別に何で区切ってもよさそうである。これを踏まえて別解の理解も頑張ろうと思う。

 

正規表現を視覚化してくれるサイト:

Regulex:JavaScript Regular Expression Visualizer