IO::Handle

ファイルハンドル、4つ目の方法。
IO::Handleでもファイルハンドルを生成できる。

https://pointoht.ti-da.net/e8883638.html
ファイルハンドルの概念を理解する - Perlゼミ - Perl元気塾のPerl講座

IO__Handle.plで、

と書く。

$ vi IO__Handle.pl
$ ls
IO__Handle.pl
$ perl IO__Handle.pl
$ ls
IO__Handle.pl  test.txt
$ cat test.txt
ABCDE
$

IO::Handleでもファイルハンドルを生成して、最終的にファイルに書き込めた。

Sample/perl/IO__Handle/IO__Handle/src/IO__Handle at master · bg1bgst333/Sample · GitHub

ファイルハンドル

ファイルハンドルの概念がわかりにくいので、ちょっと説明。

ファイルハンドルの概念を理解する - Perlゼミ - Perl元気塾のPerl講座
ファイルハンドルと出力 - 2部 Perl言語仕様 - [SMART]

上記の記事にもあるように、ファイルハンドルは具体的な実体があるわけではなく、ファイルハンドルの条件に当てはまる部分をPerlコンパイラがファイルハンドルとして認識してる模様。
シンボルの回でも、ちょっと扱ったけど、ファイルハンドルはシンボルに限らない。
でもまずはシンボルから。
file_handle.plを開いて、

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# シンボルでファイルをオープン.
my $ret = open(OUT, ">", "test.txt"); # OUTは"test.txt"を指す.
# シンボルで書き込む.
if ($ret){ # trueの時.
  print OUT "ABCDE\n"; # OUTに"ABCDE\n"を書き込む.
  close(OUT); # OUTをクローズ.
}

シンボルOUTをファイルハンドルとして認識してる。

$ vi file_handle.pl
$ perl file_handle.pl
$ ls
file_handle.pl  test.txt
$ cat test.txt
ABCDE
$

シンボルはレキシカル変数ではないので、myを付けて宣言しなくても、コンパイルできるし、strictにも引っ掛からない。
続いて、Perl 5.6未満で、使われていたという、シンボルの型グロブ。

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# シンボルでファイルをオープン.
my $ret = open(OUT, ">", "test.txt"); # OUTは"test.txt"を指す.
# シンボルで書き込む.
if ($ret){ # trueの時.
  print OUT "ABCDE\n"; # OUTに"ABCDE\n"を書き込む.
  *new_name = *OUT; # 型グロブで*new_nameに引き渡す.
  print *new_name "FGHIJ\n"; # *new_nameに"FGHIJ\n"を書き込む.
  close(*new_name); # *new_nameをクローズ.
}

*OUTから*new_nameという別の型グロブに引き渡しても、書き込みできるか。

$ vi file_handle.pl
$ rm test.txt
$ ls
file_handle.pl
$ perl file_handle.pl
String found where operator expected at file_handle.pl line 11, near "*new_name "FGHIJ\n""
        (Missing operator before  "FGHIJ\n"?)
syntax error at file_handle.pl line 11, near "*new_name "FGHIJ\n""
Execution of file_handle.pl aborted due to compilation errors.
$

ダメだった。
printでコンパイルエラー。
もしかしてprintは型グロブ形式がダメなのかな。

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# シンボルでファイルをオープン.
my $ret = open(OUT, ">", "test.txt"); # OUTは"test.txt"を指す.
# シンボルで書き込む.
if ($ret){ # trueの時.
  print OUT "ABCDE\n"; # OUTに"ABCDE\n"を書き込む.
  *new_name = *OUT; # 型グロブで*new_nameに引き渡す.
  print new_name "FGHIJ\n"; # new_nameに"FGHIJ\n"を書き込む.(*は付けない.)
  close(*new_name); # *new_nameをクローズ.
}

*を外してみた。

$ vi file_handle.pl
$ ls
file_handle.pl
$ perl file_handle.pl
$ ls
file_handle.pl  test.txt
$ cat test.txt
ABCDE
FGHIJ
$

やっぱり・・・。

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# 型グロブでファイルをオープン.
my $ret = open(*OUT, ">", "test.txt"); # *OUTは"test.txt"を指す.
# 型グロブで書き込む.
if ($ret){ # trueの時.
  print *OUT "ABCDE\n"; # *OUTに"ABCDE\n"を書き込む.
  close(*OUT); # *OUTをクローズ.
}

openに*OUTという感じでファイルハンドルの型グロブを直接指定。

$ vi file_handle.pl
$ rm test.txt
$ ls
file_handle.pl
$ perl file_handle.pl
String found where operator expected at file_handle.pl line 9, near "*OUT "ABCDE\n""
        (Missing operator before  "ABCDE\n"?)
syntax error at file_handle.pl line 9, near "*OUT "ABCDE\n""
Execution of file_handle.pl aborted due to compilation errors.
$

エラーは出てるけど、これprintだけでは。

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# 型グロブでファイルをオープン.
my $ret = open(*OUT, ">", "test.txt"); # *OUTは"test.txt"を指す.
# 型グロブで書き込む.
if ($ret){ # trueの時.
  #print *OUT "ABCDE\n"; # *OUTに"ABCDE\n"を書き込む.
  print "open success!\n";
  close(*OUT); # *OUTをクローズ.
}

printに渡すのは止めて、openとcloseだけ確認。

$ vi file_handle.pl
$ perl file_handle.pl
open success!
$

これもか・・・。
つまり、printだけファイルハンドルの型グロブがダメと。
Perl 5.6未満は、ファイルハンドルを変数に入れるのに型ブログに変換していたらしいので、それをやってみる。

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# 型グロブを変数に代入.
my $tgfh = *OUT;
# その変数でファイルをオープン.
my $ret = open($tgfh, ">", "test.txt"); # $tgfhは"test.txt"を指す.
# 書き込む.
if ($ret){ # trueの時.
  print $tgfh "ABCDE\n"; # $tgfhに"ABCDE\n"を書き込む.
  close($tgfh); # $tgfhをクローズ.
}

こうすると、

$ vi file_handle.pl
$ rm test.txt
$ perl file_handle.pl
$ cat test.txt
ABCDE
$

今度は、printでも問題なく通った。
型グロブにして変数に入れればいいのか。
さて、型ブログのリファレンスという方法もある。

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# 型グロブのリファレンスを変数に代入.
my $rtgfh = \*OUT;
# その変数でファイルをオープン.
my $ret = open($rtgfh, ">", "test.txt"); # $rtgfhは"test.txt"を指す.
# 書き込む.
if ($ret){ # trueの時.
  print $rtgfh "ABCDE\n"; # $rtgfhに"ABCDE\n"を書き込む.
  close($rtgfh); # $rtgfhをクローズ.
}

これも、

$ vi file_handle.pl
$ rm test.txt
$ perl file_handle.pl
$ cat test.txt
ABCDE
$

通る。
で、今は5.6以上なので、普通のスカラ変数でも通るのでは。

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# シンボルを変数に代入.
my $symbol = OUT;
# その変数でファイルをオープン.
my $ret = open($symbol, ">", "test.txt"); # $symbolは"test.txt"を指す.
# 書き込む.
if ($ret){ # trueの時.
  print $symbol "ABCDE\n"; # $symbolに"ABCDE\n"を書き込む.
  close($symbol); # $symbolをクローズ.
}

こうすると、

$ vi file_handle.pl
$ rm test.txt
$ perl file_handle.pl
Bareword "OUT" not allowed while "strict subs" in use at file_handle.pl line 6.
Execution of file_handle.pl aborted due to compilation errors.
$

ダメか。
でも、strictって出てるから、外せばいけるのでは。

"use strict;"コメントしたら、

$ vi file_handle.pl
$ perl file_handle.pl
$ cat test.txt
ABCDE
$

通った。
というわけで、シンボル、型グロブ、型グロブのリファレンス、という3パターンが、(一部の例外を除いて)ファイルハンドルとして認識されるのがわかった。
あと2つあったり、5.6以降の現代的な書き方があったりするけど、それは次以降で。

Sample/perl/file_handle/file_handle/src/file_handle at master · bg1bgst333/Sample · GitHub

print FILEHANDLE LIST

printにファイルハンドルを渡すことでファイルに出力できる。
その後ろにはリストを指定するのだが、文字列も1つのリスト見なせるので、今回も1つの文字列だけ出力。

Perlの組み込み関数 print の翻訳 - perldoc.jp

print.plで、

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# ファイルのオープン
my $ret = open(OUT, ">", "test.txt"); # "test.txt"を書き込みモードで開く.(ファイルハンドルはOUT.)
if ($ret){ # trueの時.
  print(OUT, "ABCDE"); # OUTに"ABCDE"を出力.
  close(OUT); # OUTをクローズ.
}

と書いて実行すると、

$ perl print.pl
No comma allowed after filehandle at print.pl line 8.
$

カンマはいらないと怒られる。

このように括弧もカンマも外してスペースだけにする。

$ perl print.pl
$ cat test.txt
ABCDE$

このように書き込まれる。
ハンドルを使う時のprintのこの挙動は不思議だ・・・。

Sample/perl/print/print_filehandle_list/src/print at master · bg1bgst333/Sample · GitHub

CGI::filefield(-name)

CGI::filefieldに-nameで名前を渡してみる。

https://pointoht.ti-da.net/e6805798.html

action.cgiで、

とすると、

test1.txtを選択して送信で
test1.txtを選択して送信で

test1.txtを選択して送信で、

今度はマルチパートでファイルが送られてるみたい・・・。
今度はマルチパートでファイルが送られてるみたい・・・。

今度はマルチパートでファイルが送られてるみたい・・・。
まあ文字化けしてるけど・・・。

Sample/perl/CGI/filefield__name/src/CGI at master · bg1bgst333/Sample · GitHub

CGI::filefield

inputタグのtype=fileは、CGI::filefieldで出せる。

https://pointoht.ti-da.net/e6805798.html

action.cgiで、

とする。
今回はfilefieldに何も指定しない。
そして、ファイルアップロードはマルチパートなので、start_formでも何も指定しない。
perlコマンドで、

$ perl action.cgi
Content-Type: text/html; charset=ISO-8859-1

<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>CGI::filefield</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<form method="post" action="http://localhost" enctype="multipart/form-data">
<input type="file" name=""  /><input type="submit" name=".submit" /></form>
</body>
</html>$

こうなる。
nameは空欄となっているのだが、

この状態でファイルを指定して送信
この状態でファイルを指定して送信

この状態でファイルを指定して送信。

しかし、ファイルバイナリは送られていない模様
しかし、ファイルバイナリは送られていない模様

しかし、ファイルバイナリは送られていない模様。
やはりnameがいるようだ。

Sample/perl/CGI/filefield/src/CGI at master · bg1bgst333/Sample · GitHub

CGI::submit

inputタグのtype=submitは、CGI::submitで出せる。

https://pointoht.ti-da.net/e7005615.html

action.cgiで、

とする。
perlコマンドだと、

$ perl action.cgi
Content-Type: text/html; charset=ISO-8859-1

<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>CGI::submit</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<form method="post" action="http://localhost" enctype="application/x-www-form-urlencoded">
<input type="text" name="key1" value="value1" /><input type="text" name="key2" value="value2" /><input type="submit" name=".submit" /></form>
</body>
</html>$

こう出る。
何も指定しない場合、nameが勝手に".submit"になってる。

HTMLだとnameが&quot;.submit&quot;だとボタンのテキストに&quot;送信&quot;がセットされるのか。
HTMLだとnameが".submit"だとボタンのテキストに"送信"がセットされるのか。

HTMLだとnameが".submit"だとボタンのテキストに"送信"がセットされるのか。

送信を押したが、name=&quot;.submit&quot;に対するvalueは送信のURLエンコードなのかな。
送信を押したが、name=".submit"に対するvalueは送信のURLエンコードなのかな。

送信を押したが、name=".submit"に対するvalueは"送信"のURLエンコードなのかな。

Sample/perl/CGI/submit/src/CGI at master · bg1bgst333/Sample · GitHub

CGI::textfield(-name,-value)

CGI::textfieldで、-nameで名前、-valueで初期値をセットする。

https://pointoht.ti-da.net/e6782591.html

action.cgiで、

2つのinputタグをtextfieldにして、-nameと-valueをセット。
perlコマンドで、

$ perl action.cgi
Content-Type: text/html; charset=ISO-8859-1

<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>CGI::textfield(-name,-value)</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<form method="post" action="http://localhost" enctype="application/x-www-form-urlencoded">
<input type="text" name="key1" value="value1" /><input type="text" name="key2" value="value2" /><input type="submit" value="submit">
</form>
</body>
</html>$

こうなるので、ブラウザは、

こっからsubmitで
こっからsubmitで

こっからsubmitで、

こうなる
こうなる

こうなる。

Sample/perl/CGI/textfield__name__value/src/CGI at master · bg1bgst333/Sample · GitHub