Perl One-Liners | Perl命令行学习2 -p和-n参数

Perl 命令行参数 -p和-n

【上集回顾】
上一次提到了-e参数,一般在使用perl的单行程序时都会加上-e参数。-e参数就是将后面引号内的内容当作perl代码执行。

这一次来说一说另外两个常见的-p和-n参数,这两个参数与输入输出相关

简介

-p:将参数当作文件读取进来,并且每次读取一行遍历文件,并把执行-e参数之后的perl代码部分得到默认变量$_打印到标准输出中(可以是屏幕也可以进入管道)。

-n:将参数当作文件读取进来,并且每次读取一行遍历文件。

两个看起来共性有点大,那有什么区别呢?

在之前先来看一个例子吧!

例子

首先新建一个文件 123.txt

里面的内容为

the string is hello
the number is 12345
the float is 1.2345

我怎么知道是不是逐行读取的呢?

123.txt所在位置右键,打开git bash here或者打开终端cd到当前目录

输入

perl -n -e '++$n;print "$n  $_"' 123.txt

# 输出为

1  the string is hello
2  the number is 12345
3  the float is 1.2345

可以看到程序部分执行了三次,文件是逐行读取的

-p参数

  • 示例1
# 比如我想让含有字符串string的行打印出来
perl -p -e 'm/string/' 123.txt

# 输出为
the string is hello
the number is 12345
the float is 1.2345

可以看到和原来的文件是没有什么两样的

  • 示例1.1
perl -p -e 's/string/number/' 123.txt

# 输出
the number is hello
the number is 12345
the float is 1.2345

第一行和之前的结果不一样了

但是假如说我想的是“只要那些有string这样字眼的行输出出来呢”?

于是我就想可不可以这样写:

  • 示例2
perl -p -e 'if(m/string/){print $_}' 123.txt

# 输出为
the string is hello
the string is hello
the number is 12345
the float is 1.2345

可以看到文件第一行输出了两次,也就是说

-p参数不管你的代码中有什么判断语句来控制输出,每读取一行都会输出一下$_,这个与代码中的print不会合并,它不管究竟有没有print

那它是输出的什么呢,输出什么时候的$_呢?

来这样玩一下

  • 示例3
perl -p -e 's/string/number/;s/hello/world/' 123.txt

# 输出为
the number is world
the number is 12345
the float is 1.2345

传进来文件第一行的变量$_在perl代码中其实变换了两次

最开始时候:the string is hello
第一次变换:the number is hello
第二次变化:the number is world

可以看到,-p参数每次输出的$_的值是它从代码执行最后的值

再来调戏一下$_;

  • 示例4
perl -p -e 'if(m/string/){$_ = "foo\n"}' 123.txt

# 输出为
foo
the number is 12345
the float is 1.2345

第一行已经变了,就是说$_是可以被改变,甚至改变巨大都可以

那为了刚才我们的目标,可以这样

  • 示例5
# 如果不能匹配到 string 就将变量$_设置为空字符串,类似于清空 
perl -p -e 'if(!m/string/){$_ = ""}' 123.txt

# 输出为
the string is hello

哈哈!没难倒我们!达到目标了!

你有没有感觉不太好呢!这里判断条件倒是很简单,所以可以这样做,假如判断条件多了,代码量多了,每次都要这样来思考不是有点不顺吗?

这样吧,开门见山,有请-n参数登场

-n参数

先来按照-p的路子试一试-n

  • 示例6
# 我想要的是将含有string字符串的行打印出来
perl -n -e 'm/string/' 123.txt

# 输出为:

是的,什么都没有,的确是这样,不是我码字把它码掉了.

其实有了上面的-p的说明,这里-n已经比较明确了,它其他方面的和-p一样,但是他不会输出$_,也就是说程序默认不会输出任何东西(当然不包括错误信息在内)

于是上面的问题就可以这样解了

  • 示例7
perl -n -e 'if(m/string/){print $_}' 123.txt

输出为:
the string is hello

到了这里大家应该明白了-p和-n的区别,其实对于命令行来说,-p和-n用的都挺多的,就看你需要什么,怎么做起来更快,就选哪一个。

问题

  1. 假如我读取文件不想要后面的换行符出现,输出的时候我自己加换行符,怎么做?

答:其实和写perl脚本一样,其实可以这样做

perl -n -e 'chomp;if(/string/){print "$_\n"}' 123.txt

也就是加一个chomp;
其实除了这种方式,还有一种加上参数-l可以达到先自动chomp,之后自动在$_后面加上\n然后输出

  1. 这个-p和-n参数的每行读取文件怎么和那个钻石操作符<>一样啊!

答:的确是这样的

# 平常写perl脚本我们一般写
open READ,"<","123.txt" or die "$!";
while(< READ >){
    ..........;
}

# 对于单行程序直接就是
perl -n -e '........' 123.txt

这样看来单行程序在写较短程序上比直接去写perl脚本来的快,来的节省

在这里再引申一下

如果我有一个fasta文件,假设名称为fasta.fasta 内容为

>cox1
ATGCGATCGTAGCATGCTAGCTACG
ACAAGCTAGCTAGCTAGCAGCATCT
ACGTGCAT
>rpl10
ATGAGCTAGCTAGCTAGACGTACGT
ACGTAG

# 假如在命令行中这样输入
perl -p -e 'if(/^>/){$_ = <> || ""}' fasta.fasta

# 输出为
ATGCGATCGTAGCATGCTAGCTACG
ACAAGCTAGCTAGCTAGCAGCATCT
ACGTGCAT
ATGAGCTAGCTAGCTAGACGTACGT
ACGTAG
  1. 为什么我一直没有输出啊!

你是不是把参数顺序写反了

  • 错误写法
    perl -e -p 'print if /string/' 123.txt
    perl -e -n 'print if /string/' 123.txt
    perl -ep 'print if /string/' 123.txt
  • 正确写法
    perl -p -e 'print if /string/' 123.txt
    perl -pe 'print if /string/' 123.txt

第三种情况虽然两个参数并在一起写了,可是有先后顺序,其实第三种就是第一种的写法。也就是说引号对引起来的代码需要靠近-e,而且-e参数一般放在所有参数最后一个

perl读取文件的方式

  • 放在命令行代码块的末尾
perl -n -e 'print $_' 123.txt
  • 结合Linux工具
cat 123.txt | perl -n -e 'print $_'
  • 使用文件句柄
perl -e '
open FILE,"<","123.txt" or die $!;
while(<FILE>){
    print $_;
}
'

版权声明:本文采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 (CC BY-NC-ND 4.0) 进行许可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容