Kodama's home / tips.

バリエーション:ディレクトリ内のファイル名を html の箇条書きにする

お題

ディレクトリ内の各ファイルに対して <li><a href="sample.html">sample.html</a></li> のように, リンクつきの箇条書きを生成する.

お好みのコマンドやスクリプト言語で書いてみる.

  1. ls の結果を変換.
  2. スクリプト言語内でファイル一覧を取って出力. (ruby で云うと Dir クラスを使う)

ls | xargs を使う例

ls -1 *html | xargs -i echo '<li><a href="{}">{}</a></li>'   

最初に書いたのはこれ. リストを取って(ls) それを処理(xargs)すると考え, 細かいオプションは後から考える事にして, 反射的に ls | xargs とやっていた.

ls | sed を使う例

文字列としての加工なら上の例よりも sed の方が簡潔.
ls -1 *html | sed -e 's|.*|<li><a href="&">&</a></li>|'   

通常は sed の s コマンドの区切り文字として | ではなく / を用いる.

awk とか perl のようなスクリプト言語の流行で sed を使う人は少なくなった?

find を使う例(1)

ls | xargs の代わりに find -exec を使ってみる.
find . -name '*html' -exec echo '<li><a href="{}">{}</a></li>' \; | sort   

find を使う例(2)

find . -name '*html' -printf '<li><a href="%P">%P</a></li>\n' | sort   

ls の結果の書き換えから離れると, これが最も自然か?

シェル(bash) の for ... in ... ; do ...done を使う例

ls | xargs の代わりにシェル(bash)の繰り返し(for)を用いた.
for f in *html;do echo '<li><a href="'$f'">'$f'</a></li>';done   

ls | gawk を使う例

ls -1 *html | gawk '{printf("<li><a href=\"%s\">%s</a></li>\n",$0,$0)}'   

この程度の処理なら sed の方が楽.

ruby を使う例(1)--- -nl による繰り返し

上を ruby で書いてみた.
ls -1 *html | ruby -nle 'printf(%Q|<li><a href="%s">%s</a></li>\n|,$_,$_)'   

ruby での繰り返しの方法としては, 大まかには以下のような手法が考えられる.

  1. -nl による暗黙の繰り返し.
    -nl オプションを使うと gawk 相当の, 入力行に対して自動的に処理を繰り返す動作になる. ワンライナー(1行スクリプト)として使うならこれが便利.
  2. イテレーター(ブロックつきのメソッド呼び出し).
    扱っているクラスに mmm{...} のような繰り返し用のメソッドがあるなら, これを使う. メンテナンス性から云うと, これを推奨.
  3. while, until, for などのループ構造.
    通常のプログラミング言語の繰り返し構文と同様に使える. 有り合わせのイテレーターでは実現できない操作の場合はこれらを使う. これを使うまえに, 該当するイテレーターが無いか探すこと.
  4. 組み込みメソッド loop{...}
    他のループでは実現できない場合 loop{...} を用いる. ループの意図が不明瞭になりやすいので, 避ける方が良い.
  5. メソッドの再帰呼び出し.
    再帰をうまく使うと繰り返しの実現が簡潔になる事がある.

通常は ruby の文字列として %Q|...| ではなく "..." を用いる.

ruby を使う例(2)---while による繰り返し

-nl を使わない場合, 明示的に while(gets);....;end で繰り返す.
ls -1 *html | ruby -e 'while(gets);chomp;printf(%Q|<li><a href="%s">%s</a></li>\n|,$_,$_);end'   

perl の while を使う例

perl で上に相当するものを書いてみた.
ls -1 *html | perl -e 'while(<>){chomp;printf("<li><a href=\"%s\">%s</a></li>\n",$_,$_)}'

シェル(bash) の while ...; do ... done を使う例

シェル(bash) で上に相当するものを書いてみた.
ls -1 *html | (while read f;do echo '<li><a href="'$f'">'$f'</a></li>';done)   

ruby を使う例(3)--- イテレーターによる繰り返し

while(gets)... を入力行に対する each{...} に置き換えた.
ls -1 *html | ruby -e 'STDIN.each{|f| f.chomp!;printf(%Q|<li><a href="%s">%s</a></li>\n|,f,f)}'   
ls -1 *html | ruby -e 'readlines.each{|f| f.chomp!;printf(%Q|<li><a href="%s">%s</a></li>\n|,f,f)}'   

上と下は見掛けはほとんど同じだが, 上では一行読み込む毎に処理しているのに対して, 下は, readlines で全体を読み込んでおいてから処理している. 複雑な操作をするならこの方が扱いやすい.

ruby を使う例(4)--- イテレーターによる繰り返し

こちらの方が ruby らしい感じがする.
ruby -e 'Dir.glob("*html").sort.each{|f| printf(%Q|<li><a href="%s">%s</a></li>\n|,f,f)}'   

Note


Kodama's home / tips.