Hatena::ブログ(Diary)

bingo_nakanishiの他言語出身者のためのPerl入門

2009-06-12

第122回 Javaはこんな風にも書けるんですな

22:52 | 第122回 Javaはこんな風にも書けるんですなを含むブックマーク

継承していきなりnewできる

ソース:

public class Hoge {
   
	public static void main(String[] args) {
    	new Object(){
	    	public void m(){ System.out.println("こんにちは"); }
	    }.m();
	}
}

結果:

こんにちは


入れ子になったコレクション

ソース:

import java.util.ArrayList;
import java.util.HashMap;


public class Foo {


	public static void main(String[] args) {
		ArrayList a  = new ArrayList();
		HashMap   t  = new HashMap();
		ArrayList a2 = new ArrayList();
		
		a.add("aaa");       a.add("bbb");
		t.put("k1", a);
		
		a2.add(t);
		
		System.out.println(((ArrayList) (((HashMap) a2.get(0)).get("k1"))).get(0));
		
	}

}

結果:

aaa

第121回 chmodのためのls -l

21:19 | 第121回 chmodのためのls -lを含むブックマーク

ls -lを実行すると

$ ls -l
total 16
-rw-r--r--  1 bingo_nakanishi  staff    0  6 12 20:15 bar.txt
-r-x------  1 bingo_nakanishi  staff    0  6  3 23:12 foo.txt
-rwxr-xr-x  1 bingo_nakanishi  staff  432  6 12 21:07 ls_n.pl
-rwxr-xr-x  1 bingo_nakanishi  staff  423  6 12 21:04 ls_n2.pl

こんな感じで、権限が rwx-のどれかで表現されるわけですが、

chmodに与えるときの引数は数字にしてやらないといけない。


chmod 755 hoge.txt

これじゃあ、コピペできないではないか!


ということで、権限を数字であらわしてくれるPerlを書いてみました。


ソース

#!/usr/bin/perl

use strict;

my $h  = {'r'=>4, 'w'=>2, 'x'=>1};

my @ls = `ls -l`;
print shift @ls;

for(@ls){
  my $rwx = (split / /, $_)[0];
  my @tmp = split //, $rwx;

  
  my $pre = sub{ my $num = 0; for(@tmp[1..3]){ $num += $h->{$_} } $num; }->()
          . sub{ my $num = 0; for(@tmp[4..6]){ $num += $h->{$_} } $num; }->()
          . sub{ my $num = 0; for(@tmp[7..9]){ $num += $h->{$_} } $num; }->();

  print $pre, $_;
}

結果

$ ./ls_n.pl 
total 16
644-rw-r--r--  1 bingo_nakanishi  staff    0  6 12 20:15 bar.txt
500-r-x------  1 bingo_nakanishi  staff    0  6  3 23:12 foo.txt
755-rwxr-xr-x  1 bingo_nakanishi  staff  432  6 12 21:07 ls_n.pl
755-rwxr-xr-x  1 bingo_nakanishi  staff  423  6 12 21:04 ls_n2.pl

行の頭に数字で表示されました。


アルゴリズムの説明

-rw-r--r--  1 bingo_nakanishi  staff    0  6 12 20:15 bar.txt

の部分から まず、

-rw-r--r--

の部分を、 $rwxに代入。

$rwxを1文字ずつばらして、@tmpに代入。

$tmp[0]は、ファイルかディレクトリかを表す部分なので、そこは、見てはいけない。なので@tmp[1..3]と1からスタート。

各無名関数に、オーナー、グループ、その他の権限を計算してもらい、その結果を文字列として連結。






ん〜でも、これだと、ls -lにしか使えない.....

これだと ls -lにしか使えないのでパイプで渡してきたのに数字を付け加えるものも書いてみました。


ソース

#!/usr/bin/perl

use strict;

my $h  = {'r'=>4, 'w'=>2, 'x'=>1};

while(<>){
  my $rwx = q/(r|w|x|-)/ x 9;

  my $pre = '';
  if($_ =~ /^.$rwx/){
    $pre = sub{ my $num = 0; for my $q($1,$2,$3){ $num += $h->{$q}; } $num; }->()
         . sub{ my $num = 0; for my $q($4,$5,$6){ $num += $h->{$q}; } $num; }->()
         . sub{ my $num = 0; for my $q($7,$8,$9){ $num += $h->{$q}; } $num; }->();
  }
    

  print $pre, $_;
}

結果

$ ls -ltr | ./ls_n2.pl 
total 16
500-r-x------  1 bingo_nakanishi  staff    0  6  3 23:12 foo.txt
644-rw-r--r--  1 bingo_nakanishi  staff    0  6 12 20:15 bar.txt
755-rwxr-xr-x  1 bingo_nakanishi  staff  423  6 12 21:04 ls_n2.pl
755-rwxr-xr-x  1 bingo_nakanishi  staff  432  6 12 21:07 ls_n.pl


正規表現は、ほとんど書いた事がないので、

なにかもっとよい方法や、まずい点にお気づきになりましたら、

教えていただけるとうれしいです。


アルゴリズムの説明

先頭が任意の文字で、r|w|x|-の文字が9つ連続した場合は、各文字を$1〜$9に記憶(先頭の任意の文字は記憶しない)。

あとは、各無名関数に、オーナー、グループ、その他の権限を計算させ、文字として連結。




おまけ

ちなみに、

sub{ }->()

のところはなにも、無名関数を使わなくても

do{  }

でもよいですね。

  my $pre = do{ my $num = 0; for(@tmp[1..3]){ $num += $h->{$_} } $num; }
          . do{ my $num = 0; for(@tmp[4..6]){ $num += $h->{$_} } $num; }
          . do{ my $num = 0; for(@tmp[7..9]){ $num += $h->{$_} } $num; };

こんな感じで。

mollifiermollifier 2009/06/13 13:41 正規表現の所は /^.[rwx-]{9}\b/ がいいんじゃないでしょうか

otnotn 2009/07/27 14:02 chmodの時に権限部分をコピペしたいという状況がちょっと想像付かない(どういうケースでしょう?)ですが、chmod の --reference オプションでは?

bingo_nakanishi_perlbingo_nakanishi_perl 2009/08/02 22:13 mollifierさん
たしかに [rwx-]{9} が良さそうですね。ありがとうございます。

otnさん
他のマシーンの環境と合わせたいときなどですね。
HOGEマシーンで ls -l で確認して、
FOOマシーンで ひたすら権限を変えるとか。
仕様書に書くときは数字で書くとか。 そういったときになります。

--referenceというオプションがあるのですね。知りませんでした。
しかし、残念ながら私のchmodには--referenceオプションはないようでした。
ですが、便利そうですので使えるマシーンがあれば試してみたいと思います。
ありがとうございました。