Perl-One-Liners-Guide

参考博客
参考博客

-e-E

-E 相比于 -e 会开启所有的 optional features.

默认的 field separation

-a 等价于 @F = splite (也就是说会设置 @F 这个数组).

输入会以 one or more sequence of whitespace characters 来分隔, 且会去除头尾的空白字符.

其会隐式开启 -n 选项, 示例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# $#F gives the index of the last element, i.e. size of array - 1
$ echo ' a b c ' | perl -anE 'say $#F'
2

# note that the leading whitespaces aren't part of the field content
$ echo ' a b c ' | perl -anE 'say "($F[0])"'
(a)
# trailing whitespaces are removed as well
$ echo ' a b c ' | perl -anE 'say "($F[-1])"'
(c)

# here's another example with more whitespace characters thrown in
# in scalar context, @F will return the size of the array
$ printf ' one \t\f\v two\t\r\tthree \t\r ' | perl -anE 'say scalar @F'
3
$ printf ' one \t\f\v two\t\r\tthree \t\r ' | perl -anE 'say "$F[1]."'
two.

输入分隔符

-F (应该是 field 吧) 来指定. 似乎其就是传递给 split 函数的参数.

其会隐式开启 -a-n 选项.

示例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# $#F gives the index of the last element, i.e. size of array - 1
$ echo ' a b c ' | perl -anE 'say $#F'
2

# note that the leading whitespaces aren't part of the field content
$ echo ' a b c ' | perl -anE 'say "($F[0])"'
(a)
# trailing whitespaces are removed as well
$ echo ' a b c ' | perl -anE 'say "($F[-1])"'
(c)

# here's another example with more whitespace characters thrown in
# in scalar context, @F will return the size of the array
$ printf ' one \t\f\v two\t\r\tthree \t\r ' | perl -anE 'say scalar @F'
3
$ printf ' one \t\f\v two\t\r\tthree \t\r ' | perl -anE 'say "$F[1]."'
two.

也可以配合正则表达式:

1
2
3
4
5
6
7
8
9
10
# count the number of vowels for each input line
# can also use: -F'(?i)[aeiou]'
$ printf 'COOL\nnice car\n' | perl -F'/[aeiou]/i' -anE 'say $#F'
2
3

# LIMIT=2
# note that the newline character is present as part of the last field content
$ echo 'goal:amazing:whistle:kwality' | perl -F'/:/,$_,2' -ane 'print $F[1]'
amazing:whistle:kwality

-F 选项之后不指定分隔符, 可以用来拆分一个单词:

1
2
3
4
5
6
$ echo 'apple' | perl -F -anE 'say $F[0]'
a

# -CS turns on UTF-8 for stdin/stdout/stderr streams
$ echo 'fox:αλεπού' | perl -CS -F -anE 'say @F[4..6]'
αλε

设置 print 和 say 等输入参数之间的分隔符

也就是把原来的分隔符替换成另外的字符.

通过设置 $, 变量:

1
2
3
4
5
6
7
8
9
10
11
12
$ perl -lane 'BEGIN{$,=" "} print $F[0], $F[2]' table.txt
brown mat
blue mug
yellow window

$ s='Sample123string42with777numbers'
$ echo "$s" | perl -F'\d+' -lane 'BEGIN{$,=","} print @F'
Sample,string,with,numbers

# default value of $, is undef
$ echo 'table' | perl -F -lane 'print @F[0..2]'
tab

设置每行截取的个数

通过调整 $#F 的值, 如:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ s='goal:amazing:whistle:kwality'

# reducing fields
$ echo "$s" | perl -F: -lane '$#F=1; print join ",", @F'
goal,amazing

# increasing fields
$ echo "$s" | perl -F: -lane '$F[$#F+1]="sea"; print join ":", @F'
goal:amazing:whistle:kwality:sea

# empty fields will be created as needed
$ echo "$s" | perl -F: -lane '$F[7]="go"; print join ":", @F'
goal:amazing:whistle:kwality::::go

$#F 设置为 -1 或者更小的值, 可以删除所有的 field:

1
2
$ echo "1:2:3" | perl -F: -lane '$#F=-1; print "[@F]"'
[]

不使用 -F 进行 fields 的分隔

利用 /regex/g 的返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ s='Sample123string42with777numbers'
# define fields to be one or more consecutive digits
# can also use: perl -nE 'say((/\d+/g)[1])'
$ echo "$s" | perl -nE '@f=/\d+/g; say $f[1]'
42

$ s='coat Bin food tar12 best Apple fig_42'
# whole words made up of lowercase alphabets and digits only
$ echo "$s" | perl -nE 'say join ",", /\b[a-z0-9]+\b/g'
coat,food,tar12,best

$ s='items: "apple" and "mango"'
# get the first double quoted item
$ echo "$s" | perl -nE '@f=/"[^"]+"/g; say $f[0]'
"apple"

固定长度分隔

利用 unpack, 或者 substr:

1
2
3
4
5
6
7
8
$ printf 'banana\x0050\x00' | perl -nE 'say join ":", unpack "Z*Z*"'
banana:50

# first field is 5 characters, then 3 characters are ignored
# all the remaining characters are assigned to the second field
$ perl -lne 'print join ",", unpack "a5x3a*"' items.txt
apple,fig banana
50 ,10 200

设置 record delimiter

可以设置 $/ 或者使用 -0 参数.

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# change the input record separator to a comma character
# note the content of the 2nd record where newline is just another character
# by default, the record separator stays with the record contents
$ printf 'this,is\na,sample,text' | perl -nE 'BEGIN{$/ = ","} say "$.)$_"'
1)this,
2)is
a,
3)sample,
4)text

# use the -l option to chomp the record separator
$ printf 'this,is\na,sample,text' | perl -lne 'BEGIN{$/ = ","} print "$.)$_"'
1)this
2)is
a
3)sample
4)text

将整个文件视作一个 record

-0777, 或者 $/ = undef:

1
2
3
4
5
6
$ cat paths.txt
/home/joe/report.log
/home/ram/power.log
/home/rambo/errors.log
$ perl -0777 -pe 's|(?<!\A)/.+/|/|s' paths.txt
/home/errors.log

将一个 paragraph 视作一个 record

-00 或者 $/ = '':

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$ cat para.txt
Hello World

Hi there
How are you

Just do-it
Believe it

banana
papaya
mango

Much ado about nothing
He he he
Adios amigo

# all paragraphs containing 'do'
# note that the record separator is preserved as there's no chomp
$ perl -00 -ne 'print if /do/' para.txt
Just do-it
Believe it

Much ado about nothing
He he he
Adios amigo

# all paragraphs containing exactly two lines
# note that there's an empty line after the last line
$ perl -F'\n' -00 -ane 'print if $#F == 1' para.txt
Hi there
How are you

Just do-it
Believe it

Perl-One-Liners-Guide
http://example.com/2023/11/13/Perl-One-Liners-Guide/
作者
Jie
发布于
2023年11月13日
许可协议