Files
devops/perl/perlonelinecn-master/02行计数.md
2025-09-17 16:08:16 +08:00

121 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 行计数
## 9.给文件打印行号。
perl -pe '$_ = "$. $_"'
和一个行代码中说明一样,“-p”作用在让Perl在命令行开启循环执行代码通过”-e”指出循环的读出输入的每一行存储在“$_”变量中执行代码接着打印出“$_”内容。
本例中我们仅仅通过修改“$_”在其前附加“$.”的内容。特定变量“$.”保存当前输入行的行号。
结果就是每一行标上了行号。
## 10.仅给非空行打印行号
perl -pe '$_ = ++$a." $_" if /./'
这行代码我们是使用了“行为if条件”语句当条件为真的时候执行行为。本例中条件是一个正则表达式“/./”,用来匹配除换行符外任何一个字符(就是匹配非空行);行为是“$_=++$a.”“_$”,由变量“$a”值在每行增加1,并附加到当前行前面。由于没有设置strict 编译,$a无需事先定义。
本语句执行结果是每一个非空行$a值1并附加到行前面。对每个空行没有任操作只输出空行。
## 11.打印文件非空行及其行号(删掉空行)
perl -ne 'print ++$a." $_" if /./'
和上例相比,本例用“-n”代替了上“-p”两者都执行行循环唯一区别是“-p”自动会打印“_$”的内容,而-n不打印所以需要用print显式打印出需要打印的内容。
由于正则不会匹配空行,所以对空行不会执行打印动作,所以就会跳过空行。
## 12.给所有行标行号,但是只打印非空行的行号
perl -pe '$_ = "$. $_" if /./'
这行代码和例10相似。我们只调整“$_”变量仅仅在匹配正则至少一个非换行字符非空行时附加行号($.)。所有其他行打印时候,没有处理,无行号。
## 13.给匹配模式行标行号,其他未匹配的仅打印。
perl -pe '$_ = ++$a." $_" if /regex/'
本行代码也是用了“行为if条件”语句但是条件是一个模式正则表达式“/regex/”。行为表现和例10一样。这儿不再赘述。
## 14.仅给匹配的行标行号和打印。
perl -lne 'print "$. $_" if /regex/'
本例和例11基本上一样唯一不同是打印匹配模式“regex/”的行。
## 15.给所有行标行号,但是打印匹配模式行的行号。
perl -pe '$_ = "$. $_" if /regex/'
本例和上一列以及例12类似。在这儿当匹配漠视的时候附加行号到当前行否则仅打印而无附加行号。
## 16.给文件标格式化的行号(模仿 cat -n
perl -ne 'printf "%-5d %s", $., $_'
这个行代码使用带格式化的“printf”打印函数打印行号。在本例中为左对齐5字符长度。
其他比较好的格式是“%5d” 表示右对其5个字符长度。“%05d”表示右对齐5字符长度用0填充长度5用00005表示
## 17.打印文件行的数量(模仿 wc -l
perl -lne 'END { print $. }'
这行代码使用“END”语句块这个语句块表现和awk中的基本一样在整个程序执行最后时候执行。本例中用“-n”参数隐藏了输入的循环过程。在所有输入循环结束后特殊变量“$.”保存了输入过的行号。“END”语句块打印出了这个变量。“-l”参数设置输出记录分割符为换行符这样我们就不必去打印“$.\n”
另一种实现方式是:
perl -le 'print $n=()=<>'
这是比较费解的一个如果你知道Perl 上下文的就好理解多了。本行代码中“()=<>”部分是个在列表上下文中的<>操作符,<>操作符会读整个文件所有行。同时,在标量上下文中,“$n”取得数量。这样“$n=()=<>”结构就等与输入的行数也就是文件的行数。print语句打印出这个数。“-l”参数使得输出数量后输出一个换行符。
下面这行代码表现也一样,除了长度不同外:
perl -le 'print scalar(()=<>)'
完全显式的版本是:
perl -le 'print scalar(@foo=<>)' 另一种方式是perl -ne '}{print $.'
这行代码使用了eskimo操作符“}{”和“-n”命令行参数。在例11中解释过“-n”参数强制Perl执行一个“while(<>){}”循环。 eskimo操作符强制Perl跳过这个循环,程序的实际执行是:
while (<>) {}{ # eskimo操作符 print $.;}
这很明显就是执行所有输入循环后,打印出“$.”,这就是行号。
## 18.打印一个文件中的非空行数
perl -le 'print scalar(grep{/./}<>)'
这行代码使用“grep”函数他的和Unix命令行同名工具功能相近。对给予的列表值“grep {condition}”返回匹配条件的值。本例中条件是一个匹配至少一个字符的正则表达式所以输入行被筛选了“grep{/./}”返回所有的非空行。为了得到列表的数量我们使用scalar函数强制其为标量上下文中这样就得到列表数量。最后打印出其结果。
一个更精妙版本的行代码还可以用“~~”代替scalar(),这能更短一点:
perl -le 'print ~~grep{/./}<>'
这还可以更短:
perl -le 'print~~grep/./,<>'
## 19.打印文件中空行的数量
perl -lne '$a++ if /^$/; END {print $a+0}'
本行代码中使用变量$a计算多少次空行结束循环后在END块打印$a值。最后输出时使用了“$a+0”结构确保文件中没有空行是打印出0。
我们也可以修改上一例的代码:
perl -le 'print scalar(grep{/^$/}<>)'
“~~”代替后的版本:
perl -le 'print ~~grep{/^$/}<>'
最后两个版本不是怎么高效,因为他们需要把整个文件读到内存再筛选。而第一个是逐行处理的。
## 20.打印文件中匹配模式的行数(模仿 grep -c
perl -lne '$a++ if /regex/; END {print $a+0}'
这个行代码基本上和前一个一样,只不过用了更一般的正则表达式/regex/