基本上,这是我编程和使用Google过去半小时的结果,试图实现一件简单的事情:从STDIN
中获取用户输入并将它们写入结构化XML文件中作为输出。下面是我丑陋的代码:
#!/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>rn";
print CARDFILE " <img>$img</img>rn";
print CARDFILE " <type>$type</type>rn";
print CARDFILE " <expansion>$expansion</expansion>rn";
print CARDFILE " <keyword>$keyword</keyword>rn";
print CARDFILE " <color>$color</color>rn";
print CARDFILE " <linkcolor>$linkcolor</linkcolor>rn";
print CARDFILE " <kickercolor>$kickercolor</kickercolor>rn";
print CARDFILE " <cost>$cost</cost>rn";
print CARDFILE " <strength>$strength</strength>rn";
print CARDFILE " <health>$health</health>rn";
print CARDFILE "</card>";
close (CARDFILE);
我是Perl的新手,但我可以说出我的代码中的一些重大问题:
使用两行首先接收
STDIN
然后chomp()
它以摆脱尾随回车。应该有单行吗?我无法弄清楚如何使用"here-doc"的东西一次性打印多行文件。如果没有
CARDFILE
文件句柄,我可以使用 here-doc 语法将所有字符串打印到单个打印语句中STDOUT
。现在我必须多次调用打印函数。对于这些
"rn"
,有没有办法使用不同的功能,这样我就不必记得在每行之后手动插入它们?
读一行
阅读单行的成语是
chomp(my $var = <>);
但我通常最终会写一个小的prompt
子例程:
sub prompt {
print @_;
chomp(my $answer = <>);
return $answer;
}
...;
my $img = prompt("img URL = ? ");
这里-文档
here-doc 只是另一种字符串文字,例如
my $str = <<"END";
foo bar
baz
END
print $str;
如果用单引号将分隔符括起来:<<'END'
,则无法将变量插入到 here-doc 中。请注意,结束标记必须始终位于行的开头,但可以包含空格字符:
my $string = <<'END THIS';
foo
bar
END THIS
# marker must be at start of line!
您可以直接打印像 here 文档
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
不同之处在于,行尾没有rn
,除非保存带有 Windows 行尾的源文件。但是,here-doc 确实包含物理换行符,并且将始终以换行符终止。
打印东西
print
函数打印由$,
特殊变量分隔的参数,然后输出$
变量。默认情况下,这两个值均为空。但是我们可以提供一个临时值:
local $ = "123";
print "foo";
输出:
foo123
当然,我们通常会将其设置为 n
.但是有一个快捷方式:只需在源代码的开头放一个use feature 'say'
或use 5.010
(或更高(,然后您就可以
say "foo";
它会自动附加换行符。
打开文件句柄
使用词法变量。使用三参数打开。进行适当的错误处理。这意味着:
use autodie;
open my $fh, "<", "filename";
或
my $filename = "filename";
open my $fh, "<", $filename or die "Can't open $filename: $!";
第二个参数是模式,>>
追加。显式指定它更安全,而不是作为文件名的一部分。
一般说明
始终use strict; use warnings;
脚本的顶部,这有助于发现问题。
人们在Perl中遇到的最大问题是他们忘记了行尾的分号。
这里的文档有两种风格。如果您在此处的文档名称周围使用双引号(或无(,它将插入变量等。
如果您在"此处文档"名称两边使用单引号,则不会进行插值。仔细观察分号和引号的位置。
#! /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!";
如果你想要一个here-document,你可以使用:
#!/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脚本,我宁愿它从命令行参数中获取数据,而不是提示它。
具有讽刺意味的是,如果使用此处文档,则无法使用输出记录分隔符来指定行尾。 无需执行任何特殊操作,即可设置:
$ = "rn";
并且每个print
输出将以 CRLF 结尾。 ($
的默认值为 undef
,因此默认情况下不会打印任何内容作为结束的行。 或者,您可以通过以下方式使代码更易于理解:
use English '-no_match_vars';
$ORS = "rn";
例如:
#!/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 = "rn";
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;
你可以做
print CARDFILE qq{<card>
<img>$img</img>
<type>$type</type>};
等等。 qq
告诉Perl插入字符串,所以它与做一个"多行字符串"是一样的。