- ベストアンサー
perlでのSTDINについて
最近、perlを独学で勉強し始めたものです。 1行で複数回データの入力を行いたいのですが、データを入力するたびに改行されてしまいます。 今は$変数=<STDIN>としているのですが、STDINで取得したデータには\nが含まれているようなので、chompを使うのかと考えているのですがどうしたらいいのか分かりません。それとも何か別の方法があるのでしょうか?
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
空白" "やタブ"\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>; と書くこともできます.
その他の回答 (4)
- __awa__
- ベストアンサー率100% (5/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";
お礼
前回のソースの使い方を誤解していたようです。 説明どおりに実行してみたら、うまくいきました。ありがとうございます。自分が思っていたものとは、若干違うようです。しかし、こちらのほうに方向転換するしかないようですね。 >$/ = " "; # 半角スペースを区切り文字に指定 my $var1 = <STDIN>; my $var2 = <STDIN>; my $var3 = <STDIN>; print "$var1\n$var2\n$var3"; 上のソースをコピペで実行したのですが、ずっと入力の要求がきっぱなしで終了しませんでした。Ctrl + C で強制終了するしかありませんでした。
- Tacosan
- ベストアンサー率23% (3656/15482)
「イメージとしては、 <STDIN> <STDIN> <STDIN> <STDIN> としたいのですが、どうでしょう?」 って, どういうことなんでしょうか? 1行に 4個 (複数個) データがあるんですか? 1度に 4行 (複数行) 入力したいんですか? 1行に複数のデータがあるとしたらその区切りは? あるいは 1度に複数行入力したいんだとしたら, その「入力単位」の区切りは?
補足
入力1 入力2 入力3 入力4 という感じで、入力1を入力しEnterを押しても改行されずに同じ行のまま入力2を入力したいということでした。 1行分のデータを、あとでsplitを使って分割し別個のデータにするのではなく、最初から別個のデータとして個別入力させたいということでした。 今回も説明が下手ですみません。
- __awa__
- ベストアンサー率100% (5/5)
>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; }
お礼
>入力されたデータを1行分文字列として取得するのは<>演算子の働きですね.ファイルハンドルを<>演算子で囲み,変数に代入(スカラーコンテキストで評価する)と1行分の文字列を返します 勉強になりました。 早速上のソースをコピペで実行しました。 実行結果 入力1回目 入力2回目 入力3回目 1回目の入力データを表示 2回目の入力データを表示 3回目の入力データを表示 となりました。実行結果だけ見ると $var1 = <STDIN>; $var2 = <STDIN>; $var3 = <STDIN>; print $var1; print $var2; print $var3; と同じようなのですが、どこが違うのでしょうか?ソースを見ただけではピンとこないもので。
- __awa__
- ベストアンサー率100% (5/5)
「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); }
補足
すみません、書き方が悪かったみたいです。 入力1 入力2 入力3 としたいのですが 入力1 入力2 入力3 となってしまっているんです。1行で何回かデータの入力をしたいということでした。すみません。
お礼
なるほど 1つのデータを取ってきて、あとで分割するということですか。 やはり、1行で個別のデータを複数取ることできないということなのでしょうか? イメージとしては、 <STDIN> <STDIN> <STDIN> <STDIN> としたいのですが、どうでしょう? STDINは入力されたデータを1行分文字列として取得すると聞いたので無理なんでしょうか?