• ベストアンサー

以下のperlのプログラムについて

以下は、多くのファイルの名前を一度に変更するための プログラムのはずなのですが・・・(参考書からもってきました) 分からないところがあるので教えて下さい。 #! /usr/bin/perl/ $op = shift or die"Usage: rename expr [files]\n"; chomp(@ARGV = <STDIN>) unless @ARGV; for(@ARGV){ $was = $_; eval $op; die $@ if $@; rename($was,$_) unless $was eq $_; } 1. opは何ですか? 2. Usageは何ですか? 3. exprは何ですか? 4. ARGVは何ですか? 5. wasは何ですか? 6. $_は何ですか? 7. eqは何ですか? 8. ファイルはどこのディレクトリに入っているものか  宣言しなくていいのですか? 9. できれば、プログラムの一行ずつ教えて頂けると助かります。 perlの初心者、というよりパソコンを使う事自体が 初心者でわからないことが多く困っています。 参考書でいろいろ調べましたが、まだ分からなくて・・・ 勉強不足で申し訳ありませんが宜しくお願い致します。

  • serus
  • お礼率50% (4/8)
  • Perl
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • tailkuppa
  • ベストアンサー率53% (52/98)
回答No.1

初心者向きのプログラムじゃないですね、これ。 Perl には「暗黙の了解」的なお約束事項が多いのですが、それを使いまくってます。 勉強したいのであれば、ちゃんとした本を買って、もう少し素直なプログラムを見て勉強した方がいいと思います。 1: #! /usr/bin/perl/ 2: 3: $op = shift or die"Usage: rename expr [files]\n"; 4: chomp(@ARGV = <STDIN>) unless @ARGV; 5: for(@ARGV){ 6:   $was = $_; 7:   eval $op; 8:   die $@ if $@; 9:   rename($was,$_) unless $was eq $_; 10:} >1. opは何ですか? 変数の名前です。 $ が先頭についている文字列は変数として扱われます。 >2. Usageは何ですか? "" で囲まれた文字列は、そのまま文字列として扱われます。 ただし、$文字列(変数) が入っている場合、変数が展開されます。 例えば、 $exp = "ほげ"; print "hogehoge$exp"; とすると、hogehogeほげが印字されるはずです。 >3. exprは何ですか? 評価: express の意味で、後に続く文字列をperl の命令として実行します。 ここでは、3行目で$op の中に設定した1番目の引数を実行します。 ファイル名の変更に使用しているのだと思います。 例えば、s/.bat/.sh/g であれば、$_ に設定された文字列のうち .bat を含んでいる場合、.bat を .sh に置き換えるという意味になります。 >4. ARGVは何ですか? プログラムを実行する際に使用された引数が中に入っている変数です。 $ rename expr hoge.txt hoge2.txt hoge3.txt のように起動した場合、 $ARGV[0] = expr $ARGV[1] = hoge.txt $ARGV[2] = hoge2.txt $ARGV[3] = hoge3.txt になります。 ただし、このプログラムでは 3 行目でshift を使用しているので、それ以降は $op = expr $ARGV[0] = hoge.txt $ARGV[1] = hoge2.txt $ARGV[2] = hoge3.txt のようにになります。 >5. wasは何ですか? $was は、変更前のファイル名だと思います。 ひとつ前の変数 >6. $_は何ですか? 暗黙の変数です。 for(配列) や、 foreach(配列) を使用した場合に、配列の中身がひとつずつ 入ってくることになっている変数です。 なので、この場合は、 $ARGV[0], $ARGV[1], $ARGV[2] の順番で値が設定されているはずです。 >7. eqは何ですか? 文字列として比較を行う演算子です。 "0001" == "1" は真、"0001" eq "1" は偽になります。 >8. ファイルはどこのディレクトリに入っているものか宣言しなくていいのですか? 単純にrename しているだけなので、このままだとこのプログラムを実行しているカレントディレクトリ上のファイルが使用されます。 指定する場合は、個々のファイル名を絶対パスで指定する必要があるでしょう。 >9. できれば、プログラムの一行ずつ教えて頂けると助かります。 1: #! /usr/bin/perl/ perl プログラム名のように指定せず、 プログラム名だけでコマンドを実行させるための マジックナンバー。 3: $op = shift or die"Usage: rename expr [files]\n"; $op にプログラムに指定された最初の引数を代入して、引数変数@ARGV の先頭を削除。 もしこれが失敗したら(例えば、引数がなかった場合など) Usage: rename expr [files](改行) を表示して終了する。 4: chomp(@ARGV = <STDIN>) unless @ARGV; もし、先頭を削除されたために@ARGV の中身がなくなったら(== もともと引数が1つしかなかった場合)、標準入力(通常はキーボード、リダイレクトしてる場合はそのリダイレクト元)からファイル名のリストを読み込む。 5: for(@ARGV){ ファイル名リストの数分だけ、ひとつひとつ処理を行う 6:   $was = $_; 変更前のファイル名として、$was を覚えておく 7:   eval $op; $op を実行して、変更後の名前を生成する。 例えば、$was = $_ = hoge.txt 、 $op = s/txt/sjis/ だった場合、 $_ は、 hoge.sjis に書き換えられる 8:   die $@ if $@; もし実行結果が失敗だったら、そのエラーメッセージを表示して終了する。 $@ はエラーメッセージが設定される変数。 9:   rename($was,$_) unless $was eq $_; 変更前後のファイル名が違っている場合だけ、変更前、後の名前を指定してファイル名の変更を行う。 10:} 5行めからのループ終了。

serus
質問者

お礼

有難うございました。 こんなに詳しく教えて頂けるとは!! 助かりました。これからはもっと頑張ります。 あと、”教えて”の回答の探し方が分からなく、勘違いして 同じ質問をしてしまいました。そっちの質問は無視して下さい。 早くパソコンに慣れなくては・・・

その他の回答 (2)

  • tailkuppa
  • ベストアンサー率53% (52/98)
回答No.3

#1 です。 expr とeval を勘違いしてたので訂正します。 expr は、文字列の中の文字なので、確かにプログラム実行には関係ありません。 regular EXPRession (正規表現)の略だと思います。 正規表現については、このスペースで説明できるような概念ではないので詳しくは 説明しませんが、特定の文字列を指し示すために使用する表現方法のことです。 ここでは複数のファイル名の共通部分を抜き出して置き換えるために使用しています。 http://www.google.co.jp/ あたりで、正規表現 で検索してみると,どんなものか見当がつくと思います. s/変換前(正規表現)/変換後/ で変換前の正規表現にマッチする最初の文字を変換後の文字列に置き換えます. s/変換前(正規表現)/変換後/g にすると,変換前の正規表現にマッチするすべての文字を変換後の文字列に置き換えます. この辺りはPerl の本領発揮な部分なので,Perl の参考書なら必ず載っているはずです.

serus
質問者

お礼

有難うございました。 あと、”教えて”の回答の探し方が分からなく、勘違いして 同じ質問をしてしまいました。そっちの質問は無視して下さい。

  • haporun
  • ベストアンサー率40% (230/562)
回答No.2

(1) shiftは対象配列の先頭要素を取り除いて返す関数です。 対象配列を指定しないときは、@ARGVが対象になります。 ここでは@ARGVの最初の要素を取り除いて返します。 もし、それができなければ、エラーメッセージを表示します。 (2)(3) Usage: 使い方。 exprは何の略だろ。 っていうか、文字列の中のものなので、プログラムと直接関係ないです。 (4) @ARGVでコマンドラインで入力された文字列が入ってきます。 たとえば、UNIXで ls /usr と入力した場合は、$ARGV[0]に '/usr' という文字列が入ってきます。 さらに多くの引数を入れた場合は、$ARGV[1]以降に入ってくるわけです。 (5) $とアルファベットで変数を表しています。 (6) $_これを、パソコン初心者と名乗るあなたに説明するすべはないような・・・。 for(@ARGV)とかくと、@ARGVのそれぞれの要素に対しての操作が可能になります。 そのとき、それの要素を表すのが$_です。 分かりませんね、次行きます。 (7) eqというのは文字列が同じかどうかを調べるための演算子です。 $a eq $bと書いたら、$aと$bが同じ文字列なら1を、違うなら''(空文字列)を返します。 (8) このスクリプトを呼び出すときに、引数として指定するのです。 (9) え? まぢで? 出直してきます(ぉ。

serus
質問者

お礼

有難うございました。 これからも質問させて頂くので宜しくお願い致します。 あと、”教えて”の回答の探し方が分からなく、勘違いして 同じ質問をしてしまいました。そっちの質問は無視して下さい。 もっと勉強してきます!

関連するQ&A

  • 以下のperlのプログラムについて教えて下さい。

    次のプログラムは”多くのファイルの名前を一度に変更する”です。 (参考書から持ってきました) perlの初心者、というよりパソコンの初心者で参考書等で調べても わからないことが多く困っています。 #! /usr/bin/perl $op = shift or die"Usage: rename expr [files]\n"; chomp(@ARGV = <STDIN>) unless @ARGV; for (@ARGV) { $was = $_; eval $op; die $@ if $@; rename($was,$_) unless $was eq $_; } 質問 1. opは何ですか? 2. Usageは何ですか? 3. exprは何ですか? 4. ARGVは何ですか? 5. evalは何ですか? 6. wasは何ですか? 7. eqは何ですか? 8. このプログラムにおいてファイルは    どこのディレクトリでもリネーム出来るのでしょうか? 9. 出来ればプログラムの一行一行について説明をして下さい。 勉強不足で申し訳ありませんが、急ぎで知りたいので 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • perlスクリプト

    perlの勉強をしているものです。人様の作ったスクリプトを解析しています。以下のスクリプトについて質問があります。 while(chomp($in = <STDIN>)){ last if ($in eq "\cD"); print "$in"; } このスクリプトに出てきている、"\cD"の意味と、ifの前に出てきているlastの働きが分かりません。またこのスクリプトは全体としてどのような仕事をするのでしょうか?? 分かる方いらっしゃいましたら、ご教授いただけると幸いです。よろしくお願いします。

  • perlのdo-while文で抜け出せない 

    perlのwhile,do-while,last文に関する質問です。 1) code1のようなプログラムを作ったのですが   eでdo_whileを抜け出すことができませんがなぜでしょうか。 ---code1(eで抜け出せない)(NG)--- my $sum=0; do{  my $a=<STDIN>;  chomp($a);  $sum=$sum+$a; }while($a ne 'e'); print $sum; -------------------------------- 2) 抜け出す方法をいろいろ試していたら   while(1)にしてlastで抜けるようにすると   code2ではeで抜け出すことができるように   なりましたが、   do~while(1)にしたcode3では、  「Can't "last" outside a loop block at …」C   というエラーが発生します。   code2とcode3はwhileがdo~whileになって   条件を見る位置がループの始めか終わりの   違いだけなのに、なぜ、code2ではOKで、   code3ではエラーになるのでしょうか。 ---code2(eで抜け出せる)(OK)----- my $sum=0; while(1) {  my $a=<STDIN>;  chomp($a);  last if ($a eq 'e');  $sum=$sum+$a; }; print $sum; --------------------------------- ---code3(エラーになる)(NG)----- my $sum=0; do{  my $a=<STDIN>;  chomp($a);  last if ($a eq 'e');  $sum=$sum+$a; }while(1); print $sum; --------------------------------- よろしくお願いします。 Windows7 , ActivePerl(v5.16.3)

    • ベストアンサー
    • Perl
  • 初心者です。perlを使用して辞書プログラムを実装する機能を作りたいのですが。

    perlを使用して辞書プログラムを実装する機能を作りたいのですが、メインプログラムを作ってからその先をどうすればいいのかわかりません。 print"1.新規作成 2.単語の登録 3.単語の検索 4.辞書一覧 5.単語の削除 6.終了:\n"; $type =<STDIN>; chomp($type); if ($type == 1) { new create; } elsif ($type == 2) { entry; } elsif ($type == 3) { search; } elsif ($type == 4) { list; } elsif ($type == 5) { deletion; } elsif ($type == 6) { exit(0); } この後はどのように作っていったらいいのでしょうか、教えて下さい。

    • ベストアンサー
    • Perl
  • perl言語のプログラム不良

    あらかじめ作った英語のテキストファイルを入力し、 文字数をカウントするプログラム(perl言語)でつくっています。 あらかたできたと思うのですが、 明らかに100文字以上あるにも関わらず なぜか3文字とカウントされます。 どこが不具合がわかる方いましたら よろしくお願いいたします。 以下が問題のプログラムです。 print"読み込むファイル名を入力してください。\n"; $input_file = <STDIN>; open(INPUT, "$input_file") or die "$!"; sub count_words{ my @ words = split(/\W+/,$_[0]); my $num_words=@ words; } $num_words = &count_words($input_file); print"単語数は$num_wordsです。"; close(INPUT);

  • Perlによるディレクトリ内の連続的な大量データ処理

    Perlのテキスト処理に関する質問です.やりたいことはあるディレクトリ内に10000個ほどの(1)のようなテキストデータがあります.ここで私は(2)のプログラムを作成しました.しかしながら,このプログラムだと10000個あるテキストデータの一つしか処理できません.この処理内容をディレクトリ全体に適用させる方法はありますでしょうか?File::Find::Ruleなどがネット上にあったので使おうと努力しましたができませんでした.どなたかよろしくお願いします. (1)  2020 01 01 00 109.18970 18.36816 -2.317 -2.459 292.712 0.013 91.276 30.618 292.712 0.013 -2.317 -2.459 998.793 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 2020 01 01 00 109.54297 18.39178 -2.702 -2.652 292.653 0.013 90.044 30.676  292.653 0.013 -2.702 -2.652 993.902 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ・ ・ ・ ・ (2) use warnings; open INFILE, '<', '2020-01-01_00.txt' or die "file open error: $!"; while( <INFILE> ){ chomp if( /\n$/ ); $Year = substr($_,0,4); chomp if( /\n$/ ); $Month = substr($_,5,2); chomp if( /\n$/ ); $Day = substr($_,8,2); chomp if( /\n$/ ); $Time = substr($_,11,2); chomp if( /\n$/ ); $Lon = substr($_,16,9); chomp if( /\n$/ ); $Lat = substr($_,29,8); chomp if( /\n$/ ); $Temp = substr($_,57,7); chomp if( /\n$/ ); $Hum = substr($_,76,6); chomp if( /\n$/ ); $Ozone = substr($_,85,6); chomp if( /\n$/ ); $Rad = substr($_,140,5); $data = $Year. "-".$Month."-".$Day." ".$Time." ".$Lon." ".$Lat." ".$Ozone." ".$Rad." ".$Hum." ".$Temp."\n"; open($data, ">", "data.txt") or die("error :$!"); } # ファイルを閉じる close INFILE; exit;  

  • 簡易grep関数ができません。助けてください><

    はじめまして。 C言語初級者の大学生です。 このたび、大学で出た課題で、Perlで製作した簡易grep関数 プログラムを元に、C言語で同様の内容をプログラミングせよ、 という課題が出題されました。 大半はできたのですが、肝心の文字列検索アルゴリズム(特定のワードを含んだ文章の検出)がわかりません。 やり方教えてください、お願いします>< OS:Mac OS X 10.8.5 エディタ:vi Editor 【参考】 Perlで製作した簡易grep関数 #grep for perl version #usage:mygrep pattern file1,file2,... if(@ARGV<1) {die:"Usage mygrep pattern [file.]\n";} $pattern=shift foreach $file (@ARGV) { open(FILE,$file); $line=1; while(<FILE>){ #--------------------------------------------- print "$file $line:$_" if /$pattern/o; #--------------------------------------------- # ↑この部分をC言語で表したいです $line++;} close(FILE); }

  • Perlのプログラミングについて

    Perlのプログラミングでつまづきました。 # ファイルから指定文字列を含む行を収集する # 入力ファイルのオープンと読み込み print( "入力ファイル名?" ); $n = <STDIN>; chomp( $n ); open( FIN, "<$n" ) or die "入力ファイルオープンエラー: $!\n"; $n = @a = <FIN>; close( FIN ); print( "$n 行読み込みました\n" ); # 行の収集 print( "検索文字列?" ); $x = <STDIN>; chomp( $x ); $ptn = $x; #指定の文字列 $x = @b = grep( /$ptn/, @a ); print( "$x 行見つかりました\n" ); # 出力ファイルのオープンと書き出し print( "出力ファイル名?" ); $y = <STDIN>; chomp( $y ); open( FOUT, ">$y" ) or die "出力ファイルオープンエラー: $!\n"; print FOUT ( $ptn, "\n" ); print FOUT ( $x, "\n" ); print FOUT ( @b ); close( FOUT ); というプログラムで実行すると C:\My Perl\pl>perl プログラムの実行.pl 入力ファイル名?sample1.txt 168 行読み込みました 検索文字列?k 45 行見つかりました 出力ファイル名?out3-24.txt 続行するには何かキーを押してください . . . となり出力ファイルの中身が表示されません。 どこを間違えているのかご指摘いただけないでしょうか?

  • Windows 用 Emacs で、shell で困ってます

    perl のプログラムを、Emacs の shell で実行すると,打ったコマンドが、次の行に現れて、プログラムがうまく動いてくれません。たとえば、 print "Enter a first number: "; chomp($one = <STDIN>); の部分が、プリントされないのです。何も表示されてないところへ、数を入力すると、最後にまとめてプリントされます。  Emacs をカスタマイズすれば直るものでしたら、嬉しいんですが。  ちなみに、perl は、Active Perl です。 どなたか、わかる方がおられましたら、ご教示願います。

  • perl初心者です。宜しくお願い致します。

    ファイルの容量が大きく。perlを使用してデータの集計をしています。 "A"がきたらflag1をたてなさい。 "B"がきたらflag2をたてなさい。 "C"がきたらflag3をたてなさい。 これでAとBとCを抜き取ること&AからCまでの時間を取得したのですが、 Bの数のmaxの値だけを抜き取りたいのですが、Bがきたときの数をすべて 出力してしまいます。下記の文だと、Bが4回きたら、1,2,3,4と出力してしまいます。 それで4だけを出力したいのですがどのように書き換えたらようか教えて頂けますでしょうか。 '----------------------------------------------------------------------------- open (IN,"< $ARGV[0].txt") or die; open (OUT,"> $ARGV[0]_out.txt") or die; $flag =0; my $a, $b, $c; $count = 0; ####################################################### while($line =<IN>){ ($time,$data) = split(/\s+/,$line); if($data eq "A") { $flag=1; $a = $time; #print OUT $line; #print OUT "\n"; } elsif($data eq "B"){ $flag=2; $count++; $count == $data; print OUT ("$count\n") } #print OUT ("$count\n"); elsif($data eq "C"){ $flag=0; $count=0; $b = $time; $c = $b - $a; print OUT ("time $c\n") } } -------------------------------------------------------------------------------