• ベストアンサー

perlでのSTDINについて

最近、perlを独学で勉強し始めたものです。 1行で複数回データの入力を行いたいのですが、データを入力するたびに改行されてしまいます。 今は$変数=<STDIN>としているのですが、STDINで取得したデータには\nが含まれているようなので、chompを使うのかと考えているのですがどうしたらいいのか分かりません。それとも何か別の方法があるのでしょうか?

  • Perl
  • 回答数5
  • ありがとう数3

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

  • ベストアンサー
  • __awa__
  • ベストアンサー率100% (5/5)
回答No.2

空白" "やタブ"\t"で入力を区切りたければ,splitを使えばよさそうです. my $input = <STDIN>; my ($var1, $var2, $var3) = split /\s+/, $input; とすると,$var1~$var3に$varsを\s+(1文字以上のスペース文字)にマッチする正規表現で区切った値が代入されます. 例えば, abc defg [タブ] hij[改行] と入力すると,$var1, $var2, $var3にはそれぞれ'abc','defg','hij'が代入されます. 入力されるデータ数が一定でなければ,配列を使って my $input = <STDIN>; my @ary = split /\s+/, $input; とすれば,$ary[0],$ary[1],$ary[2],...に値が代入されます. また,$inputを使わず, my @ary = split /\s+/, <STDIN>; と書くこともできます.

shaka001
質問者

お礼

なるほど 1つのデータを取ってきて、あとで分割するということですか。 やはり、1行で個別のデータを複数取ることできないということなのでしょうか? イメージとしては、 <STDIN> <STDIN> <STDIN> <STDIN> としたいのですが、どうでしょう? STDINは入力されたデータを1行分文字列として取得すると聞いたので無理なんでしょうか?

その他の回答 (4)

  • __awa__
  • ベストアンサー率100% (5/5)
回答No.5

入力1回目[改行] 入力2回目[改行] 入力3回目[改行] という入力では,<STDIN>を使った場合と結果は同じですね.入力を 入力1回目 入力2回目 入力3回目[改行] 入力1回目[タブ]入力2回目[タブ]入力3回目[改行] などとして実行してみるとどうでしょうか.1行の入力で同じ出力結果が得られませんか. このあたりの動作を理解するには,バッファリングに関する知識が必要になります.バッファリングとは,入力や出力を効率的に行うため,文字列をバッファという場所に一時的に保存しておき,後で一気に受け渡しを行う(フラッシュする)処理のことです.この場合,改行を入力した時点でバッファのフラッシュが行われます. バッファリングに関して,詳しくは検索してみてください. 画面が改行されるのは,あなたが入力した改行がそのまま画面に表示されるからです.入力同士の区切り文字としてデフォルトでは改行が指定されているので,「入力 → 改行(区切り文字&バッファのフラッシュ) → 入力 → 改行(区切り文字&バッファのフラッシュ) → 入力 → 改行(区切り文字&バッファのフラッシュ)」という動作をすることになります. <STDIN>を使った場合でも,区切り文字に改行以外の文字を指定することで,1行の入力による複数値の取得ができるようです.ただし,バッファのフラッシュのために必要となる,最後の改行は必須です. 次のスクリプトを実行して,「入力 → 半角スペース(区切り文字) → 入力 → 半角スペース(区切り文字) → 入力 → 半角スペース(区切り文字) → 改行(バッファのフラッシュ)」という入力を行ってみてください. $/ = " "; # 半角スペースを区切り文字に指定 my $var1 = <STDIN>; my $var2 = <STDIN>; my $var3 = <STDIN>; print "$var1\n$var2\n$var3";

shaka001
質問者

お礼

前回のソースの使い方を誤解していたようです。 説明どおりに実行してみたら、うまくいきました。ありがとうございます。自分が思っていたものとは、若干違うようです。しかし、こちらのほうに方向転換するしかないようですね。 >$/ = " "; # 半角スペースを区切り文字に指定 my $var1 = <STDIN>; my $var2 = <STDIN>; my $var3 = <STDIN>; print "$var1\n$var2\n$var3"; 上のソースをコピペで実行したのですが、ずっと入力の要求がきっぱなしで終了しませんでした。Ctrl + C で強制終了するしかありませんでした。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

「イメージとしては、 <STDIN> <STDIN> <STDIN> <STDIN> としたいのですが、どうでしょう?」 って, どういうことなんでしょうか? 1行に 4個 (複数個) データがあるんですか? 1度に 4行 (複数行) 入力したいんですか? 1行に複数のデータがあるとしたらその区切りは? あるいは 1度に複数行入力したいんだとしたら, その「入力単位」の区切りは?

shaka001
質問者

補足

入力1 入力2 入力3 入力4 という感じで、入力1を入力しEnterを押しても改行されずに同じ行のまま入力2を入力したいということでした。 1行分のデータを、あとでsplitを使って分割し別個のデータにするのではなく、最初から別個のデータとして個別入力させたいということでした。 今回も説明が下手ですみません。

  • __awa__
  • ベストアンサー率100% (5/5)
回答No.3

>STDINは入力されたデータを1行分文字列として取得すると聞いたので無理なんでしょうか? 入力されたデータを1行分文字列として取得するのは<>演算子の働きですね.ファイルハンドルを<>演算子で囲み,変数に代入(スカラーコンテキストで評価する)と1行分の文字列を返します. 必要性は感じられませんが,1行の入力に対してSTDINから複数の値を取得したければ,readやgetcを使って書けそうです. 深く考えずに書いたのであまり自信がありませんが,以下のスクリプトを試してみてください. my $var1 = &read_string; my $var2 = &read_string; my $var3 = &read_string; print "$var1\n$var2\n$var3\n"; # 標準入力から文字列を得るサブルーチン sub read_string{ my $str; while(my $c = getc STDIN){ last if($c =~ /\s/); # スペース文字なら取得を終了 $str .= $c; # 文字を$strの末尾に連結 } return $str; }

shaka001
質問者

お礼

>入力されたデータを1行分文字列として取得するのは<>演算子の働きですね.ファイルハンドルを<>演算子で囲み,変数に代入(スカラーコンテキストで評価する)と1行分の文字列を返します 勉強になりました。 早速上のソースをコピペで実行しました。 実行結果 入力1回目 入力2回目 入力3回目 1回目の入力データを表示 2回目の入力データを表示 3回目の入力データを表示 となりました。実行結果だけ見ると $var1 = <STDIN>; $var2 = <STDIN>; $var3 = <STDIN>; print $var1; print $var2; print $var3; と同じようなのですが、どこが違うのでしょうか?ソースを見ただけではピンとこないもので。

  • __awa__
  • ベストアンサー率100% (5/5)
回答No.1

「1行で複数回データの入力」というのが引っかかりますが, たとえば5行分の文字列を改行を含めずに得たければ, my $var; chomp($var .= <STDIN>) for(1 .. 5); と書けばよいかと思います. これに対して, abc[改行] de[改行] fghi[改行] jklmnop[改行] qrst[改行] と入力すると,$varの中身は"abcdefghijklmnopqrst"となります. 決まった行数でなく空行によって入力を終了したければ,次のようにしてみてください. my $var; while((my $line = <STDIN>) ne "\n"){ chomp($var .= $line); }

shaka001
質問者

補足

すみません、書き方が悪かったみたいです。 入力1  入力2  入力3 としたいのですが 入力1 入力2 入力3 となってしまっているんです。1行で何回かデータの入力をしたいということでした。すみません。

関連するQ&A

  • 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 続行するには何かキーを押してください . . . となり出力ファイルの中身が表示されません。 どこを間違えているのかご指摘いただけないでしょうか?

  • [Perl] Pack関数について教えてください。

    こんにちは。 下記は、pack関数のサンプルスクリプトですが、 なんでそのような結果になるのか、よくわかりません。どなたか教えていただけますか。 print "文字列を入力してください:"; $string = <STDIN>; chomp ($string); $length = length($string); print "数値を入力してください:"; $number = <STDIN>; chomp ($number); # Do Pack! $packed = pack("A${length}i", $string, $number); print "パック文字列: $packed\n"; --- 結果 --- 文字列を入力してください:perl 数値を入力してください:100 パック文字列: perl

    • ベストアンサー
    • Perl
  • Perlにおけるレコードセパレータについて

    Perl初心者、現在独学中です。 複数プラットフォームで作られたテキストベースのデータファイル群を ファイルハンドルから開き readline で読み込む際、3つの改行文字の 全てに入力レコードセパレータ(特殊変数$/)を対応させたいのですが、 どのようにすれば良いのでしょうか。 ファイルサイズが大きいもので500~600MB程ありますので undef $/; で 全て読み込むのは余り現実的ではなく1行ずつ評価したいのです。 無理なようでしたら、代替案(ファイルの先頭64KBだけを読み込む等)を ご教示頂きたいと思います。

    • ベストアンサー
    • Perl
  • STDIN

    入力待ちにならないようにSTDINを使いたいのですが、 通常はどのような方法を取るのでしょうか? 定期的なチェックが出来るだけで構いません。 普通は別プロセスを立ち上げるのでしょうか? その時はどのような方法が楽でしょうか? またプロセス間通信はどのような方法を取るのが一般的ですか? いくつかの一般化された方法があるなら複数でも構いません。

  • STDINの挙動がよく分かりません

    POST形式で読み込んだデータを3通りで書きだしてみました。しかしながら1番最初のファイルにしかデータは書き出されていません。 ひょっとしてSTDINはコンピュータがアクセスしてきた時の行を覚えていて、次のアクセスがあった時はそこから処理が行われるのでしょうか。それなら1度ファイルに全ての入力データを書き出した際にアクセスポイントはファイルの最後になっているから、2度目、3度目の書き出しの際はループが廻るはずがありません。 そこで書き出しまえに$-を書き出してみました。でも1度目のループを行う前から値は0。 前にファイルハンドル名など何かを付けなくては$-は死んでいるのかと思って、$=を書き出してみると60という値を取ります。でも書き出された1度目のループのファイルを数えてみると$=80なんです。何なんでしょう、この60という値は。 どうもSTDINの挙動が分からないのですが、どういう理由でこうなっているのか。どうしたら3回ループを廻すことが出来るのかご教授いただけないでしょうか。 ********************************************** #!/usr/bin/perl -d use CGI; use SR; open(OUT,'>stdin_main.txt'); print OUT $-."\n"; print OUT $=."\n"; while(<STDIN>) { print OUT $_; } close(OUT); &SR::parse_form; our $q=new CGI; print $q->header(-charset=>'utf-8'), $q->start_html(-charset=>'utf-8', -lang=>'ja-JP'), $-,"<br />\n", $=,"<br />\n"; while(<STDIN>) { print $_; } print $q->end_html; ********************************************** package SR; sub parse_form { open(OUT,'>stdin_SR.txt'); print OUT $-."\n"; print OUT $=."\n"; while(<STDIN>) { print OUT $_; } close(OUT); } 1;

    • ベストアンサー
    • Perl
  • パールで「$:」は何を意味するのですか??

    パールプログラムの先頭に次の行がありました。 $: = " "; これはいったい何をやっているのでしょうか。 $:という変数へ1文字分の空白文字を代入しているというのは分かるのですが・・・ ちなみにパール起動直後にこの変数の内容を表示させてみたら_(下線)でした・・・。 パールではこの$:という変数は何に使用されているのですか。

    • ベストアンサー
    • Perl
  • STDINによるキーボードからの入力について

    初めて質問させて頂きます。 最近Perlの勉強をはじめ、perlによるネットワークプログラミングに興味が出てきたので、 自分でインスタントメッセンジャーの様な物を作ってみようと思いました。 1つのwhileループ内で、 "受信データがある場合はその内容を表示" "クライアントへの入力があった場合はその内容を送信" という動作をさせたいのですが、 <STDIN>で入力待機状態となるとループが止まるので、受信→内容表示の処理が滞ってしまいます。 while(1){ if(受信内容がある){ print "受信内容"; } if($senddata=<STDIN>){ #ここで止まってしまう為、受信表示ができない print $ソケット "$senddata"; } } 入力待ちをすれば、止まってしまうのは当たり前と言うことはわかっているのですが・・・。 過去の質問に、スレッドを利用して "受信があればそれを表示"と"入力があればそれを送信" の動作を分けている方がいらっしゃいましたが、 スレッドで分けずにこの動作を実現する事はできるのでしょうか? また、可能ならばどの様にしたら良いのでしょうか?

    • ベストアンサー
    • Perl
  • perlの内容なのですがこれで合っていますでしょうか?

    print 関数は文字列や数値だけでなく、変数を指定してその値を表示することもできます。 $a=1; 1を$aに代入する。 print $a; 変数$aの値を表示させる。 $a=2; 変数$aに2を代入する。 $b=3; 変数$bに3を代入する。 print "変数\$aに変数\$bを代入\n"; 「変数$aに変数$bを代入」という文字を表示させて改行する。 $a=$b; 変数$bの値を変数$aに代入する。 print "\$a="; 「$a=」を表示させる。 print $a; 変数$aの値を表示させる。 print ",\$b="; 「,$b=」を表示させる。 print $b; 変数$bの値を表示させる。 print "\n"; 改行を表示させる。 実行結果は↓↓↓↓↓↓↓ 変数$aに変数$bを代入 $a=3,$b=3 変数の書き方 文は ; で区切るが、1行に並べることも可能。 $a=2; $b=3; ↓ $a=2; $b=3; 複数の変数に、同時に値を代入することも可能。 $a=2; $b=2; ↓ $a=$b=2;

    • ベストアンサー
    • Perl
  • PerlからPythonについて

    以下のPerlをPythonで書くとどうなるのでしょうか? pythonのヒアドキュメントと<DATA>, chompの動作の置き換えが知りたいです。 ヒアドキュメントは"""や'''で可能?と思いますが、ヒアドキュメントを1行づつ取り出す方法がわかりません。 use strict; # <-- Pythonの厳格化?の警告方法も知りたいです。 while(<DATA>){ chomp; print "$_\n"; } exit; __DATA__ abc de f ghi 参考になるサイトや本をご存じの方教えてください。

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

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

専門家に質問してみよう