7

STDIN基本的に、これは、ユーザー入力を取得して構造化された XML ファイルに出力として書き込むという単純なことを達成しようとして、過去 30 分間 Google を使用してプログラミングを行った結果です。以下は私の醜いコードです:

#!/bin/perl
print "img URL = ?    ";
$img = <>;
chomp($img);
print "filename = ?    ";
$filename = <>;
chomp($filename);

# now write xml with inserted contents to a file:
open (CARDFILE, ">>$filename");
print CARDFILE "<card>\r\n";
print CARDFILE "    <img>$img</img>\r\n";
print CARDFILE "    <type>$type</type>\r\n";
print CARDFILE "    <expansion>$expansion</expansion>\r\n";
print CARDFILE "    <keyword>$keyword</keyword>\r\n";
print CARDFILE "    <color>$color</color>\r\n";
print CARDFILE "    <linkcolor>$linkcolor</linkcolor>\r\n";
print CARDFILE "    <kickercolor>$kickercolor</kickercolor>\r\n";
print CARDFILE "    <cost>$cost</cost>\r\n";
print CARDFILE "    <strength>$strength</strength>\r\n";
print CARDFILE "    <health>$health</health>\r\n";
print CARDFILE "</card>";
close (CARDFILE);  

私は Perl を初めて使用しますが、コードの重大な問題のいくつかを知ることができました。

  1. 2 行を使用して最初に受信しSTDIN、次にchomp()それを受信して​​末尾のキャリッジ リターンを取り除きます。ワンライナーが必要ですか?

  2. 「here-doc」を使用して複数行を一度にファイルに出力する方法がわかりません。CARDFILEファイル ハンドルがなければ、 here-doc 構文を使用して、すべての文字列をSTDOUT1 つの print ステートメントで出力できます。ここで、印刷関数を複数回呼び出す必要があります。

  3. これら"\r\n"の s について、別の関数を使用して、各行の後に手動で挿入することを忘れないようにする方法はありますか?

4

4 に答える 4

11

行を読む

1 行を読むイディオムは次のようになります。

chomp(my $var = <>);

promptしかし、私は通常、小さなサブルーチンを書くことになります:

sub prompt {
  print @_;
  chomp(my $answer = <>);
  return $answer;
}
...;
my $img = prompt("img URL = ? ");

ヒアドキュメント

ヒアドキュメントは単なる別の種類の文字列リテラルです。

my $str = <<"END";
foo bar
baz
END
print $str;

区切り文字を一重引用符で囲む場合: <<'END'、変数をヒアドキュメントに補間することはできません。終了マーカーは常に行の先頭にある必要がありますが、スペース文字を含めることができることに注意してください。

    my $string = <<'END THIS';
    foo
    bar
END THIS
    # marker must be at start of line!

次のようなヒアドキュメントを直接印刷できます

print CARDFILE <<"END";
<card>
    <img>$img</img>
    <type>$type</type>
    <expansion>$expansion</expansion>
    <keyword>$keyword</keyword>
    <color>$color</color>
    <linkcolor>$linkcolor</linkcolor>
    <kickercolor>$kickercolor</kickercolor>
    <cost>$cost</cost>
    <strength>$strength</strength>
    <health>$health</health>
</card>
END

ここでの違いは\r\n、Windows の行末でソース ファイルを保存する場合を除いて、行末に何もないことです。ただし、ヒアドキュメントには物理的な改行が含まれており、常に改行で終了します。

モノを印刷する

この関数は、特殊変数でprint区切られた引数を出力し、変数を出力します。デフォルトでは、これらは両方とも空です。しかし、一時的な値を提供できます。$,$\

local $\ = "123";
print "foo";

出力:

foo123

もちろん、通常は に設定し\nます。ただし、ショートカットがあります。ソース コードの先頭にuse feature 'say'or use 5.010(またはそれ以上) を配置するだけで、次のことができます。

say "foo";

自動的に改行を追加します。

ファイルハンドルを開く

レキシカル変数を使用します。3 引数オープンを使用します。適切なエラー処理を行います。これは、次のいずれかを意味します。

use autodie;
open my $fh, "<", "filename";

また

my $filename = "filename";
open my $fh, "<", $filename or die "Can't open $filename: $!";

2 番目の引数は、追加用のモードです>>ファイル名の一部としてではなく、明示的に指定する方が安全です。

一般的な注意事項

これは常にuse strict; use warnings;スクリプトの先頭にあり、問題の発見に役立ちます。

于 2013-07-05T00:18:42.077 に答える
8

Perl のヒア ファイルに関する大きな問題は、行末のセミコロンを忘れていることです。

ヒアドキュメントには 2 つの種類があります。ヒア ドキュメント名を二重引用符で囲む (または使用しない) と、変数などが補間されます。

ヒア ドキュメント名を一重引用符で囲んだ場合、補間されません。セミコロンと引用符の配置に注意してください。

#! /usr/bin/env perl
#
use warnings;
use strict;
use feature qw(say);

my $foo = "The value of foo";
my $bar = "The value of bar";

my $heredoc =<<"END_HERE_1";
This is my first here document
and this will interpolate things
like $foo and $bar.

Heck, it even shows up correctly
in Vim.
END_HERE_1

say "$heredoc"; # All set

print  <<'END_HERE_2';
This is my first here document
and this will NOT interpolate things
like $foo and $bar.

Heck, it even shows up correctly
in Vim.
END_HERE_2

say "And that's all folks!";
于 2013-07-05T00:05:52.070 に答える
3

ヒアドキュメントが必要な場合は、次を使用できます。

#!/usr/bin/env perl
use strict;
use warnings;

print "img URL = ?    ";
chomp(my $img = <>);
print "filename = ?   ";
chomp(my $filename = <>);

# now write xml with inserted contents to a file:
open my $CARDFILE, ">>", $filename or die "Failed to open file $filename for writing";
my $type = "unregimented";
my $expansion = "contracted";
my $keyword = "lock";
my $color = "green";
my $linkcolor = "blue";
my $kickercolor = "red";
my $cost = '$0.00';
my $strength = "humungous";
my $health = "excellent";

print $CARDFILE <<EOF;
<card>\r
    <img>$img</img>\r
    <type>$type</type>\r
    <expansion>$expansion</expansion>\r
    <keyword>$keyword</keyword>\r
    <color>$color</color>\r
    <linkcolor>$linkcolor</linkcolor>\r
    <kickercolor>$kickercolor</kickercolor>\r
    <cost>$cost</cost>\r
    <strength>$strength</strength>\r
    <health>$health</health>\r
</card>\r
EOF

close $CARDFILE;

圧縮された入力に注意してください。データは垂直方向に並んでいます。ただし、Perl スクリプトを数回実行したので、データを要求するよりも、コマンド ライン引数からデータを取得したほうがよかったと思います。

皮肉なことに、ヒア ドキュメントを使用する場合、出力レコード セパレータを使用して行末を指定することはできません。特別なことをしなくても、次のように設定できます。

$\ = "\r\n";

print出力は CRLF で終了します。( のデフォルト値$\undefであるため、デフォルトでは行末として何も出力されません。) あるいは、次の方法でコードをよりわかりやすくすることができます。

use English '-no_match_vars';

$ORS = "\r\n";

例えば:

#!/usr/bin/env perl
use strict;
use warnings;
use English '-no_match_vars';

print "img URL = ?    ";
my $img = <>;
chomp($img);
print "filename = ?    ";
my $filename = <>;
chomp($filename);

# now write xml with inserted contents to a file:
open my $CARDFILE, ">>", $filename or die "Failed to open file $filename for writing";
my $type = "unregimented";
my $expansion = "contracted";
my $keyword = "lock";
my $color = "green";
my $linkcolor = "blue";
my $kickercolor = "red";
my $cost = '$0.00';
my $strength = "humungous";
my $health = "excellent";

$ORS = "\r\n";

print $CARDFILE "<card>";
print $CARDFILE "    <img>$img</img>";
print $CARDFILE "    <type>$type</type>";
print $CARDFILE "    <expansion>$expansion</expansion>";
print $CARDFILE "    <keyword>$keyword</keyword>";
print $CARDFILE "    <color>$color</color>";
print $CARDFILE "    <linkcolor>$linkcolor</linkcolor>";
print $CARDFILE "    <kickercolor>$kickercolor</kickercolor>";
print $CARDFILE "    <cost>$cost</cost>";
print $CARDFILE "    <strength>$strength</strength>";
print $CARDFILE "    <health>$health</health>";
print $CARDFILE "</card>";

close $CARDFILE;
于 2013-07-05T00:19:28.757 に答える
0

あなたはただすることができます

print CARDFILE qq{<card>
<img>$img</img>
<type>$type</type>};

等々。qqPerl に文字列を補間するように指示するので、「複数行の文字列」を実行するのと同じです。

于 2013-07-04T23:56:47.960 に答える