Rust 生命周期
生命周期太难了, 哭了。
网易云音乐歌单
看剧不如听歌。
语法
Rust 语法太难记了, 反直觉。又哭了。
关于
Perl 6 is died, Long live Raku.
学习正则表达式
regexes in raku is awesome!
学习 Grammar
学习 Action
Action in raku is awesome!
Web Site
- ohmycloud ✔
- ohmycloudy ✔
- ohmysummer ✔
- ohmyshunny ✔
- ohmysunny ✔
- ohmyraku ✔
- ohmypanda ✔
- ohmyweekly ✔
- rakulang ✔
提取 ipconfig 命令的部分输出
数据样例
下面这段文本是 IPCONFIG /ALL
命令的输出结果:
Windows IP 配置
主机名 . . . . . . . . . . . . . : Win10-2020QJFDK
主 DNS 后缀 . . . . . . . . . . . :
节点类型 . . . . . . . . . . . . : 混合
IP 路由已启用 . . . . . . . . . . : 否
WINS 代理已启用 . . . . . . . . . : 否
以太网适配器 本地连接* 9:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
描述. . . . . . . . . . . . . . . : Sangfor SSL VPN CS Support System VNIC
物理地址. . . . . . . . . . . . . : 00-FF-05-0D-13-A2
DHCP 已启用 . . . . . . . . . . . : 否
自动配置已启用. . . . . . . . . . : 是
无线局域网适配器 WLAN:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
描述. . . . . . . . . . . . . . . : Realtek RTL8192EU Wireless LAN 802.11n USB 2.0 Network Adapter
物理地址. . . . . . . . . . . . . : 30-B4-9E-40-FF-0C
DHCP 已启用 . . . . . . . . . . . : 是
自动配置已启用. . . . . . . . . . : 是
无线局域网适配器 本地连接* 10:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
描述. . . . . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter
物理地址. . . . . . . . . . . . . : 32-B4-9E-40-FF-0C
DHCP 已启用 . . . . . . . . . . . : 是
自动配置已启用. . . . . . . . . . : 是
以太网适配器 以太网:
连接特定的 DNS 后缀 . . . . . . . :
描述. . . . . . . . . . . . . . . : Realtek PCIe GBE Family Controller
物理地址. . . . . . . . . . . . . : 54-E1-AD-48-66-22
DHCP 已启用 . . . . . . . . . . . : 否
自动配置已启用. . . . . . . . . . : 是
本地链接 IPv6 地址. . . . . . . . : fe80::4195:49da:a7ec:9e68%6(首选)
IPv4 地址 . . . . . . . . . . . . : 192.168.0.68(首选)
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.0.1
DHCPv6 IAID . . . . . . . . . . . : 324329901
DHCPv6 客户端 DUID . . . . . . . : 00-01-00-01-26-4E-B2-11-54-E1-AD-48-66-22
DNS 服务器 . . . . . . . . . . . : 61.128.128.68
TCPIP 上的 NetBIOS . . . . . . . : 已启用
分别提取含有"适配器"文字下面的「描述」、「物理地址」、「IP地址」、「子网掩码」、「默认网关」、「DNS 服务器」等信息。某些适配器下面可能实际没有「IP地址」、「子网掩码」、「默认网关」、「DNS 服务器」等,有就提取,没有就略过。
Grammar
unit grammar IPConfig::Grammar;
token TOP { <section>+ %% \n* }
token section {
<header>
\n
<config>+
}
token header { ^^ \N+ \n }
token config { ^^ \s+ \N+ $$ \n* }
Action
unit class IPConfig::Action;
method TOP($/) {
make $/<section>».made;
}
method section($/) {
my $configs = $/<config>».made;
if $configs.elems > 0 {
make ~$/<header> ~ $configs.join('');
} else {
make Empty;
}
}
method header($/) {
make ~$/;
}
method config($/ is copy) {
my $text = ~$/;
if $text.contains(/'描述' | '物理地址' | IPv[4|6] ' ' 地址 | '子网掩码' | DNS ' ' 服务器/) {
$/.make(~$/);
} else {
make Empty;
}
}
提取脚本
use lib '.';
use IPConfig::Grammar;
use IPConfig::Action;
my $ipconfig = IPConfig::Grammar.parsefile(
"data/ifconfig.txt",
:actions(IPConfig::Action)
).made;
.Str.say for @$ipconfig;
输出
以太网适配器 本地连接* 9:
描述. . . . . . . . . . . . . . . : Sangfor SSL VPN CS Support System VNIC
物理地址. . . . . . . . . . . . . : 00-FF-05-0D-13-A2
无线局域网适配器 WLAN:
描述. . . . . . . . . . . . . . . : Realtek RTL8192EU Wireless LAN 802.11n USB 2.0 Network Adapter
物理地址. . . . . . . . . . . . . : 30-B4-9E-40-FF-0C
无线局域网适配器 本地连接* 10:
描述. . . . . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter
物理地址. . . . . . . . . . . . . : 32-B4-9E-40-FF-0C
以太网适配器 以太网:
描述. . . . . . . . . . . . . . . : Realtek PCIe GBE Family Controller
物理地址. . . . . . . . . . . . . : 54-E1-AD-48-66-22
本地链接 IPv6 地址. . . . . . . . : fe80::4195:49da:a7ec:9e68%6(首选)
IPv4 地址 . . . . . . . . . . . . : 192.168.0.68(首选)
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.0.1
DNS 服务器 . . . . . . . . . . . : 61.128.128.68
使用 %% 提取文本块儿
数据样例
section.txt 中的本文为样例数据:
123,456,789
=begin code
999,333,666
145,123,120
=end code
10,20,30
10,10,10
=begin code
567,555,578
678,679,665
710,720,715
=end code
321,654,987
=begin code
312,555
=end code
要求把 =begin code
和 =end code
之间的所有数字分别提取出来。
Grammar
Grammar 的结构如下, 其中 Section 目录下分别是 Grammar 和 Action 模块, data 目录下是样例数据 section.txt:
├── Section
│ ├── Actions.pm6
│ └── Grammar.pm6
├── data
│ ├── section.txt
├── extract-section.p6
use Grammar::Debugger;
use Grammar::Tracer;
unit grammar Section::Grammar;
token TOP {
^ <section>+ %% <separator> $
}
token section {
<line>+
}
token line {
^^ [\d+]+ %% ',' $$ \n
}
token separator {
| ^^ '=begin code' $$ \n
| ^^ '=end code' $$ \n*
}
其中 Grammar::Debugger
和 Grammar::Tracer
模块用于调试 grammar, 需要放在 grammar 模块的行首:
use Grammar::Debugger;
use Grammar::Tracer;
Action
unit class Section::Actions;
method TOP($/) {
make $/.values».made;
}
method section($/) {
make ~$/.trim;
}
method line($/) {
make ~$/.trim;
}
method separator($/) {
make Empty;
}
解析
不使用 Action
use lib '.';
use Section::Grammar;
my $parsed = Section::Grammar.parsefile(@*ARGS[0] // 'data/section.txt');
.Str.say for $parsed<section>;
输出
123,456,789
999,333,666
145,123,120
10,20,30
10,10,10
567,555,578
678,679,665
710,720,715
321,654,987
312,555
使用 Action
use lib '.';
use Section::Grammar;
use Section::Actions;
my $parsed = Section::Grammar.parsefile(
@*ARGS[0] // 'data/section.txt',
:actions(Section::Actions)
).made;
.Str.say for @$parsed;
输出
123,456,789
999,333,666
145,123,120
10,20,30
10,10,10
567,555,578
678,679,665
710,720,715
321,654,987
312,555
再用 %% 提取文本块儿
数据样例
Here's some unimportant text.
=begin code
This code block is what we're after.
We'll use 'ff' to get it.
=end code
More unimportant text.
=begin code
I want this line.
and this line as well.
HaHa.
=end code
More unimport text.
=begin code
Let's to go home.
=end code
Grammar
use Grammar::Debugger;
use Grammar::Tracer;
unit grammar Range::Grammar;
token TOP {
^ <un-important-line>+ %% <section> $
}
token section {
<begin> ~ <end> <line>+?
}
token un-important-line {
^^ \N+ )> \n*
}
token line {
^^ \N+ )> \n*
}
token begin {
^^ '=begin code' $$ \n*
}
token end {
^^ '=end code' $$ \n*
}
Action
unit class Range::Actions;
method TOP($/) {
make $/.values».made;
}
method section($/) {
make $/<line>».made;
}
method line($/) {
make ~$/.trim;
}
method un-important-line($/) {
make Empty;
}
method begin($/) {
make Empty;
}
method end($/) {
make Empty;
}
提取
#!/usr/bin/env perl6
use lib '.';
use Range::Grammar;
use Range::Actions;
my $parsed = Range::Grammar.parsefile(
@*ARGS[0] // 'data/flip-flop.txt',
:actions(Range::Actions)
).made;
for @$parsed -> $line {
say $line.raku;
say '-' x 35;
}
输出
$["This code block is what we're after.", "We'll use 'ff' to get it."]
-----------------------------------
$["I want this line.", "and this line as well.", "HaHa."]
-----------------------------------
$["Let's to go home."]
-----------------------------------
提取文本块儿
数据样例
Here's some unimportant text.
=begin code
This code block is what we're after.
We'll use 'ff' to get it.
=end code
More unimportant text.
=begin code
I want this line.
and this line as well.
HaHa
=end code
More unimport text.
=begin code
Let's to go home.
=end code
要求提取 =begin code
和 =end code
之间的文本块儿。
Grammar
grammar ExtractSection {
token start { ^^ '=begin code' \n }
token finish { ^^ '=end code' \n }
token line { ^^ \N+)> \n }
token section { <start> ~ <finish> <line>+? }
token comment { ^^\N+ \n }
token TOP { [<section> || <comment>]+ }
}
Action
class ExtractSectionAction {
method TOP($/) { make @<section>».ast.List }
method section($/) { make ~«@<line>.List }
method line($/) { make ~$/.trim }
method comment($/) { make Empty }
}
提取
my $em = ExtractSection.parse(
$excerpt,
:actions(ExtractSectionAction)
).ast;
for @$em -> $line {
say $line.perl;
say '-' x 35;
}
输出
$("This code block is what we're after.", "We'll use 'ff' to get it.")
-----------------------------------
$("I want this line.", "and this line as well.", "HaHa")
-----------------------------------
$("Let's to go home.",)
-----------------------------------