开始单行程序!

建议:后面的代码最好你自己也输入一下感受一下

我是用的Windows进行演示的,在Mac和Linux上也是一样的(终端) 首先写几个示例代码

例子

  • 示例1
1
2
3
4
perl -e 'print "Hello World!"'

# 输出
Hello World!
  • 示例2
1
2
3
4
perl -e 'my $str = 'asdfghasd';$str =~ s/a/%/g;print "$str"'

# 输出
%sdfgh%sd
  • 示例3
1
2
3
4
perl -e 'for(1..10){print "$_ "}'

# 输出
1 2 3 4 5 6 7 8 9 10

发现规律没, perl -e '' 是他们的共同结构,其中关键的是-e参数,它意思就是

在其后面的引号里面的东西当作perl代码来执行。

这个岂不是不需要写pl脚本就可以做很多事情了。是的,就是这样,不过有些东西有些差别,以后再说。 你现在可以在-e后面的的引号(建议用单引号,不然可能报错,然后还会牵扯到其他问题)里面输入perl代码试一试。

用法

1
perl -e '代码'

问题

  • 换行

我想换行继续输入,按了一下回车,结果代码直接执行了。呃,尴尬, 单行程序和之前的写在代码编辑器里面的不一样,假如我们想换行输入代码我们可以这样做,我们先不把引号对打全,只打出单个,也就是这样:

1
perl -e '

继续:

1
perl -e 'my $str = "asdfghasd";

按一下回车输入其他内容:

1
2
3
perl -e 'my $str = "asdfghasd";
$str =~ s/a/%/g;
print "$str";

最后加上末尾的引号,完整代码为:

1
2
3
4
5
6
perl -e 'my $str = "asdfghasd";
$str =~ s/a/%/g;
print "$str";'

# 输出
%sdfgh%sd

有人可能会问,为什么不输入 \ 符号来续行呢?好,来试一试:

1
2
3
4
5
6
7
perl -e 'my $str = "asdfghasd";\
$str =~ s/a/%/g;\
print "$str";'

# 输出
Can't modify single ref constructor in substitution (s///) at -e line 2, near "s/a/%/g;"
Execution of -e aborted due to compilation errors.

出错了!因为之前说过了,在-e参数之后的引号内东东都会被认为是perl代码,所以这个引号里面不能这么做,在引号外的命令被视为是shell的命令,在shell中的续行的方法就是在代码换行之前输入\ 然后再按下回车,就可以继续输入代码了。

1
2
3
4
5
6
7
8
9
# shell代码
echo 123 \
qwe \
asd
# 等价于
echo 123 qwe asd

# 输出
123 qwe asd

既然有这种方式,能不能利用一下

1
2
3
4
5
perl -e '$n = 1;' \
-e 'print $n'

#输出
1

这种方法利用输入\ 实现了续行,但是我们可以看到 \ 是不在引号对之内,所以属于shell命令。

注意:这里有两个-e参数,之后引号内的内容当作perl命令执行,同时还可以看到,看似我们使用两个-e把程序打断了,变量$n的内容还被保存,没有丢,但是一旦在执行下一个perl命令的时候它就没有了:

1
2
3
4
5
6
perl -e '$n = 1;' \
-e 'print $n' \
| perl -e ' print "n is $n\n";'

# 输出
n is

变量$n是空的,所以在执行一个perl内的变量会暂时保存,但是一旦用管道隔开,变量就消失了,perl单行程序重新开始。

  • 引号

刚才前面说到了在-e参数后面要用''(单引号),最好不要用""(双引号),不然shell中的变量和perl的变量会搞混

1
2
3
4
5
6
7
8
# shell中的变量
varname=123
# 然后在perl中声明同样名字的变量
perl -e "my $varname = 'asd';print $varname"

# 输出
syntax error at -e line 1, near "my 123"
Execution of -e aborted due to compilation errors.

按照错误说明,其实在声明这个变量的时候就出错了,也就是perl外部变量与内部变量的混淆了,为了避免这种事情发生,我建议使用单引号对。

如果偏要这么做的话也不是不行,那直接转义咯!

1
2
3
4
5
varname=123
perl -e "my \$varname = 'asd';print \$varname"

# 输出为
asd

但是实际上,使用双引号你可能觉得可以进行shell向perl传递变量。但是,每次使用perl自己的变量还要在 $ 前面加上\来转意,这太麻烦了!perl变量传递还有更好的做法,所以不推荐使用双引号对。

后记

其实话说回来,One-Liners说的单行程序,一般来说的确就是写在一行上面,也就是说代码量不多的情况下,但其实有的时候还是有必要进行换行的,那样更容易修改和理清程序,这里其实是为了表明Perl是那种很能干的特质,就像在《Learning Perl》这本书里面说的那样:

骆驼长得也有点丑陋,但是它们努力工作,哪怕是在严酷的环境下也一样不辞辛劳。骆驼能在种种不利的条件下帮你把事情搞定,尽管它长相丑陋,气味难闻,偶尔冷不丁的还对你吐上几口口水。

补充

今天看《perl技术内幕》突然发现还有一种命令行运行perl代码的方式:

  • 用法
1
2
3
4
5
# 输入perl之后,在后面写上短横线,然后换行
perl -
代码
# 最后使用__END__标记来结束代码
__END__

但是我发现这种方法无法接受管道的数据,而且比较丑陋!

更多

但是这本书都是介绍的一些小技巧,并没有比较系统的说明各个参数之间的关联以及各个参数的具体功能,但是当你熟知这些参数之后回头去看这本书会得到一定的启发。


应用

其实只是用这样一个参数就可以干活了(因为-e后面的引号内的东西作为perl代码来执行,也就是说某种程度上就是写perl脚本) 例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 有一个文件123.txt
# 内容为
Hello World!
--------------------------------------
# perl
perl -e '
open FILE,"<","123.txt" or die $!;
while(<FILE>){
print $_;
}
'
--------------------------------------
# 输出
Hello World!

再比如:

1
2
3
4
5
6
7
8
9
cat 123.txt | perl -e '
while(<>){
print $_;
}
'
--------------------------------------
# 输出
Hello World!
'

但是实际上很多时候并不方便,仅仅使用-e参数孤掌难鸣,-e参数是一个大头,也是必不可少的。俗话说的好,“一个好汉三个帮”,还需要搭配其他的参数来完成更加快捷简洁方便的方法来。

今天的-e参数就说到这里,后面还有更好玩的参数哦!我刚学perl单行程序,有哪些地方说错了请多多指教,多谢了!

我学习Perl单行程序的经历

刚开始看Perl的时候(那时候还没有接触编程的东西),我看到了老师写了一些程序,于是想这个Perl到底是什么样的语言,还可以在那种黑乎乎的东西(shell)里面这样写,当时在网上查了一下各个参数的意思,刚开始不明白,想着这都是些什么玩意啊!就把笔记本丢到一边去了。再后来,我看到了知乎的这个问题,突然想起来还有这个用法,然后慢慢的一边看老师的代码,一边自己练习。慢慢的我就开始使用这门“独门奇招”,谈不上熟练,只是觉得好用,有时候觉得没必要写脚本就迫使自己写单行程序,现在有时候不直接写perl脚本,而是直接上perl单行程序搭配shell的工具使用。