markmap website
# Perl markmap document
## STDIN/OUT
### STDOUT
- print:不会自动换行
- printf:格式化打印
- say:需要perl版本支持,会自动换行,类似于print函数
### STDIN
- chomp($var_name = \<STDIN>)
- chomp(@array = \<STDIN>)
- if file name have special character: use <<>> [double diamond reference](https://www.effectiveperlprogramming.com/2015/05/use-perl-5-22s-operator-for-safe-command-line-handling/)
## Build-in warnings
- use warnings;
- perl -w perl_program.pl
- #!/usr/bin/perl -w
## 引号
- 单引号:单引号内除了单引号和反斜线可以被转义,其他字符都是字面意思
- 双引号:双引号内可以内插变量,通过转义字符转义,表达式内插
- [q qq qw qr qx difference URL](https://programmerall.com/article/64241961690/)
- q():等价于单引号,括号可以使用其他符号替代
- qq():等价于双引号,括号可以使用其他符号替代
- qw():在每个字符串上加上单引号,括号可以使用其他符号替代
- qr():创建一个正则表达式,括号可以使用其他符号替代
- qx():等价于反引号,括号可以使用其他符号替代
- ```
引用字符出现起止符需要转义
say qq{abc\}def}; # 转义终止符
say qq{abc\{def}; # 转义起始符
say qq ad\aefa; # 转义起始符a,输出daef
```
- ```
#双引号内可以变量内插,单引号内不能变量内插
say "hello $name"; # hello junma
say 'hello $name'; # hello $name
say "hello\\world"; # hello\world
say 'hello\\world'; # hello\world
say "hello\"world, hello'world"; # hello"world, hello'world
say 'hello\'world, hello"world'; # hello'world, hello"world
```
## Heredoc
### 注意事项
- Heredoc end-mark不加引号,默认值为双引号
- Heredoc end-mark前后不能有空格,end-mark前后一致
### 变量可解析
- ```
my $var = value;
my $message = <<"MSG";
This \$var is $var;
MSG
```
### 变量不可解析
- ```
my $var = value;
my $message = <<'MSG';
This \$var is $var;
MSG
```
## 运算符号
### 数值运算符
- 1. \+ \- \* /:常规四则运算
2. \*\*:幂指数运算
3. %:模运算
4. ++ --:自增/自减操作
5. 数学运算过程会先尝试将结果转化为整数,如果有精度损失则保持浮点数格式
### 比较运算符
- ```
数值 字符串 意义
-----------------------------
== eq 相等
!= ne 不等
< lt 小于
> gt 大于
<= le 小于或等于
>= ge 大于或等于
<=> cmp 返回值-1/0/1
```
### 逻辑运算符
- ```
not expr # 逻辑取反
expr1 and expr2 # 逻辑与
expr1 or expr2 # 逻辑或
! expr # 逻辑取反
expr1 && expr2 # 逻辑与
expr1 || expr2 # 逻辑或
expr1 // expr2 # 逻辑定义或
```
### 按位运算符
- ```
& 按位与
| 按位或
^ 按位异或
~ 按位取反
<< 按位左移
>> 按位右移
```
## 标量
### 私有变量
- my:仅在当前作用域起作用
- local:在当前作用域及子作用域起作用
- state:变量在子程序调用过程中,保存之前的结果,仅适用于标量
### 数值标量
- $varname:单个数据的存储空间
- $varname = value
- ```
数值表示:
二进制:0b[0-1]
八进制:0[0-7]
十六进制:0x[0-f]
数字之间可以使用下划线进行分隔,便于阅读
$n = 1234; # 十进制整数
$n = 34_123_456;
$n = 33_22_56;
$n = 0b1110011; # 二进制整数
$n = 01234; # 八进制整数
$n = 0x1234; # 十六进制整数
$n = 12.34e-56; # 指数定义方式
$n = "-12.34e56"; # 字符串方式定义的数值
$n = "1234"; # 字符串方式定义的数值
$n = " 1234"; # 有前缀空白的字符串数值
$n = " 123a"; # 可以当数值123使用,但warnings时会警告
```
### 标量数值相关函数
- 1. int():截断为整数
2. rand():生成[0,1)之间的随机数
3. abs():返回数值的绝对值 [abs usage URL](https://www.geeksforgeeks.org/perl-abs-function/)
4. hex():十六进制转换为十进制,参数一般为十六进制数值**字符串,数值本身会转换为十进制再处理**,变量需要进行处理
5. oct():十六进制/八进制/二进制转换为十进制,参数一般为进制数值**字符串,数值本身会转换为十进制再处理**,变量需要进行处理
- ```
hex() usage:
1. hex('0xff'):对应数值255
2. hex("0xff"):对应数值255
3. hex(0xff):对应数值597,等价于hex('0x255')
4. $num=0xff;hex($num);对应数值597
5. $num='0xff';hex($num);对应数值255
```
### 字符串标量
- \$varname = 'value' or \$varname = "value"
- ```
字符转换操作
\u 修改下一个字符为大写
\l 修改下一个字符小写
\U 修改后面所有字符大写
\L 修改后面所有字符小写
\Q 使后面的所有字符都成为字面符号
\E 结束\U \L或\Q的效果
```
### 标量字符串相关函数
- 1. lc:后面的字符全部转换为小写
2. uc:后面的字符全部转换为大写
3. fc:unicode编码字符全部转换为小写
4. lcfirst:第一个字符转换为小写
5. ucfirst:第一个字符转换为大写
6. chr():asicii码或unicode码转换为对应字符
7. ord():字符转换为asicii码或unicode码
8. chomp:去除行尾换行符
9. chop:去除行尾字符
10. index:获取字符在字符串中的索引位置
11. substr:字符串提取子字符串
## 数组
### 数组声明和引用
- 数字数组声明:@array_name=(num1,num2,num3,...);
- 字符串数组声明:@array_name=('str1','str2','str3',...);
字符串数组声明:@array_name=qw(str1 str2 str3 ...); 字符串存在空格不能使用这种方法
- 数组引用:$array_name[index],索引值可以为负数,反向索引
- **数组最后一个索引值**:${#array_name}
- **数组长度**:scalar @array_name
### 数组扩展
- @array_name=(@array_name,val1,val2,...);原数组基础上加新的数值
- @array_merge=(@array_name1,@array_name2,...);多个数组拼接成新的数组
- @array_name=(val1,val2,val3,...)[num1,num2,num3,...];列表切片,指定数值赋值给数组;
### 遍历数组方法
- ```
#for usage
for my $val (@arr) {
say "$val";
}
```
- ```
#foreach usage
forach my $val (@arr) {
say "$val";
}
```
- ```
#控制变量在遍历数组后其数值不变
my @arr = (11, 22, 33, 44);
my $v = 3333;
say \$v;
say '---- before ----';
for my $v (@arr) { say \$v; }
say '---- after ----';
say \$v;
say "$v";
# 输出:
# SCALAR(0x22f3d10)
# ---- before ----
# SCALAR(0x2277ab0)
# SCALAR(0x2277a98)
# SCALAR(0x2277b40)
# SCALAR(0x2277b58)
# ---- after ----
# SCALAR(0x22f3d10)
# 3333
```
### 数组相关函数
- push:数组尾部追加元素或列表,返回追加完后的数组长度
- pop:移除并返回数组最后一个元素
- shift:移除并返回数组第一个元素
- unshift:数组首部添加一个元素或列表,返回追加完后的数组长度
- keys:返回数组索引值
- values:返回数组元素值
- ```
# splice
1. splice @array:清空数组,返回被移除的元素
2. splice @array,offset:删除offset处到末尾的所有元素,返回被移除的元素
3. splice @array,offset,length:offset处开始向后删除length个元素,返回被移除的元素
4. splice @array,offset,length,list:offset处开始向后删除length个元素,删除部分用list替代,返回被移除的元素
offset为负数:删除从offset处,length个元素
length为负数:保留length个参数
# =================================================== #
@arr=qw(perl py php shell ruby java c c++ js);
@new_arr=splice @arr,2,-2; # 从php开始删除,最后只保留c++和js两个元素
say "original arr: @arr"; # 输出:perl py c++ js
say "new arr: @new_arr"; # 输出:php shell ruby java c
```
### 列表相关函数
- 1. 列表重复 x: my @arr = (1,2) x 3
- 2. join:列表元素用给定字符连接起来 join "-" qw(a b c e)
- 3. split:使用给定分隔符将字符串划分为列表,分隔符支持正则表达式
- ```
#split usage
split /PATTERN/,EXPR,LIMIT
split /PATTERN/,EXPR
split /PATTERN/
split
```
- reverse():返回列表反转数值,不改变列表原有顺序
- sort():返回列表重排后的数值,不改变列表原有顺序
## 条件判断语句
- ```
if(cond_true) {
cmd;
}elsif(cond_true) {
cmd;
}else {
cmd;
}
```
- ```
unless(com_fals) {
cmd;
}
# unless也可以接elsif/else,通常不会这样用
```
- ```
# 三元运算符
cond? con_true:con_false;
```
- ```
# 实用的单行if mode
say "Debug information" if($DEBUG_EN == 1);
```
## 循环语句
- last:类似于break,跳出循环体
- next:类似于continue,跳过当前循环进入下一个循环
- redo:重新执行一遍循环体
- lable:
- ```
# while语句
while(cond_true) {
cmd;
}
```
- ```
# until语句
until(con_false) {
cmd;
}
```
- ```
# for/foreach循环
for (expr1; expr2; expr3) {
...
}
foreach (expr1; expr2; expr3) {
...
}
```
- ```
# for/foreach遍历
for my $i (LIST) {}
for (LIST){}
foreach my $i (LIST) {}
foreach (LIST){}
```
- ```
# 纯语句块即单独一个大括号,只循环一次的循环结构
{...}
```
## 哈希
### 哈希赋值
- %hash_name:多个键值对数据的存储空间
- 使用胖逗号,尾部可以加上一个逗号方便扩展
- 使用胖逗号,key可以省略单引号(自动补上单引号)
- %hash_name = (key1,value1,key2,value2 ...);
- %hash_name = (key1 => "value1",key2 => "value2",);
### 判断哈希是否为空
- ```
# hash have at least one key-value
if(%hash_name){
say "This hash is not empty"
}
```
### 哈希数值遍历
- ```
while(my ($key,$value) = each %hash_name){
say "The key $key value is $value";
}
foreach my $key (keys %hash_name){
say "The key $key value is $value";
}
for my $key (keys %hash_name){
say "The key $key value is $value";
}
```
### 哈希函数
- keys: my @k = keys %hash_name;返回键-列表
- values: my @v = values %hash_name;返回值-列表
- exists: exists $hash_name{'key'};键值对是否存在
- delete: delete $hash_name{'key'};删除键值对
## 引用
- 变量sigil符号前加上反斜线表示变量的引用
- 引用可以查看变量保存的数据的内存地址
- 不同类型的变量的引用,打印引用值结果也不同
- ```
my $name = "junma";
my @arr = qw(a b c);
my %h = ( name => "junma", age => 23 );
say \$name; # SCALAR(0x55ad7f974dc8)
say \@arr; # ARRAY(0x55ad7f974738)
say \%h; # HASH(0x55ad7fa99150)
```
## 子程序
- ```
sub sub_fun{
cmd;
}
sub sub_fun(){
cmd;
}
```
- ```
#调用
1. sub_fun;
2. sub_fun();
3. &sub_fun;
4. &sub_fun();
```
- 参数:子程序的参数会存放在@\_中,通过\$\_[0],$\_[1]等依次获取
## 正则表达式
### 匹配
- 正则匹配基本形式:string =~ /pattern/
- 正则匹配的严格形式:string =~ m/pattern/,使用双斜线时m可以省略
- m后面可以接其他成对的字符:m## m%% m() m!!来替换m//
- 正则表达式匹配的项是\$\_,则可以简写;**\$_ =~ /paattern/等价于 /pattern/**
### 替换
- 替换形式:s/match_text/new_text/
- 替换形式:tr/match_text/new_text/
- 替换形式:y/match_text/new_text/
### 匹配修饰字
- i: 不区分大小写
- s: dot元字符可以匹配换行符
- x: 忽略匹配项中的空格
### 替换修饰字
- g: 全局替换
- m:匹配多行
- e:替换并当作命令执行
- ee:两次替换并当作命令执行
## 文件读写
### 打开文件
- 语法格式:open FILE_HANDLE,"mode","file_path/file_name" or die "prompt message";采用三段式,通过句柄打开文件。
- r mode:read only
- w mode:write/create/truncate
- r+ mode:read/write
- w+ mode:read/write/create/truncate
- a mode:write/create/append
- a+ mode:read/write/create/truncate
### 读文件
- ```
# line by line
while(chomp(my $line = <FILE_HANDLE>)){
cmd;
}
```
- ```
# store in an array
chomp(my @array = <FILE_HANDLE>)
```
- ```
# store in a scalar
my $content;
open(my $fh, '<', $filename) or die "cannot open file $filename";
{
local $/;
$content = <$fh>;
}
close($fh);
```
### 写文件
- ```
# FILE_HANDLE不需要用引号包围
# FILE_HANDLE和写入的字符间没有逗号/分号
print FILE_HANDLE "strings that want write to file";
printf FILE_HANDLE "strings that want write to file";
say FILE_HANDLE "strings that want write to file";
```
### 关闭文件
- close(FILE_HANDLE);
## 文件测试
- ```
if(-r filename and -w ){
}
```
- ```
if(-r -w filename){
}
```
- [file test operate reference webpage](https://www.geeksforgeeks.org/perl-file-test-operators/)
- -r checks if the file is readable
- -w checks if the file is writable
- -x checks if the file is executable
- -o checks if the file is owned by effective uid
- -R checks if file is readable by real uid
- -W checks if file is writable by real uid
- -X checks if file is executable by real uid/gid
- -O checks if the file is owned by real uid
- -e checks if the file exists
- -z checks if the file is empty
- -s checks if the file has nonzero size (returns size in bytes)
- -f checks if the file is a plain text file
- -d checks if the file is a directory
- -l checks if the file is a symbolic link
- -p checks if the file is a named pipe (FIFO): or Filehandle is a pipe
- -S checks if the file is a socket
- -b checks if the file is a block special file
- -c checks if the file is a character special file
- -t checks if the file handle is opened to a tty
- -u checks if the file has setuid bit set
- -g checks if the file has setgid bit set
- -k checks if the file has sticky bit set
- -T checks if the file is an ASCII text file (heuristic guess)
- -B checks if the file is a “binary” file (opposite of -T)
## 目录操作
- glob('dir_path/file_type')
- opendir(DIR_HANDLE,dir)
- @dir_list = readdir(DIR_HANDLE)
- closedir(DIR_HANDLE)