某些 DS 代码系统不太支持类别。此表达式是以编程方式将类别与代码名称组合起来的最有效方法吗?
perl -ne '$data = $_ ; $cat = $1 if $data =~ /CAT (.*)/ ; $cde = $1 if $data =~ /CODE \d (.*)/ ; print "$cat, $cde\n" if /CODE \d /' 'Mario Kart DS (USA).mch'
示例 1 - melonDS、Mario Kart DS(美国).mch
CAT Mission 1 Codes
CODE 0 3 Star Rank - Mission 1-1
223D00C4 0000000F
CODE 0 3 Star Rank - Mission 1-2
223D00C5 0000000F
CAT Mission 2 Codes
CODE 0 3 Star Rank - Mission 2-1
223D00CD 0000000F
CAT Mission 3 Codes
CODE 0 3 Star Rank - Mission 3-1
223D00D6 0000000F
输出:
Mission 1 Codes, 3 Star Rank - Mission 1-1
Mission 1 Codes, 3 Star Rank - Mission 1-2
Mission 2 Codes, 3 Star Rank - Mission 2-1
Mission 3 Codes, 3 Star Rank - Mission 3-1
正则表达式无法捕获 CAT 并将其添加到 CODE 前面。这是我能想到的最好的表达方式:
perl -0777 -pe 's/CAT (.*)(?s).+?(?-s)(?:CODE \d (.*)(?s).+?(?-s))+(?=CAT|CODE|\z)/\1, \2\n/gi' 'Mario Kart DS (USA).mch'
为了搜索和替换,我必须捕获以 CAT 开头的每组 CODE。 perl -0777 和 (?s)(?-s) 允许我slurp输入文件并将 CODE 匹配锚定到初始 CAT 匹配,同时跨过行尾。我可以重复 CODE 匹配,作为捕获组 2,但它只能得到最后一个。
上面的表达式如下所示: 对于以“CAT”开头到行尾的行,以最不贪婪的方式跨行,直到到达 CODE。对于以“CODE [number]”开头的每个组,捕获到行尾,然后跨行直到到达 CAT、CODE 或文件末尾。尽可能多次重复代码组。
对于上面的示例,这是输出:
Mission 1 Codes, 3 Star Rank - Mission 1-2
Mission 2 Codes, 3 Star Rank - Mission 2-1
Mission 3 Codes, 3 Star Rank - Mission 3-1
最佳答案
在这种情况下,争论什么是最有效的或什么不是最有效的可能并不是太有趣。如果您有一个可行的解决方案,那么也许就足够了。
这是另一种基于段落模式的解决方案。
-00
:将输入记录分隔符设置为空字符串$/= ''
,这会启用段落模式。行结尾被视为\n\n
。-l
自动chomp-E
启用say
(因为与 print 和 -l 存在交互)
然后,如果/^CAT/则存储 header ,否则清理并打印。
$ perl -00 -nlwE'if (s/^CAT //) { $k = $_ } else { s/^CODE \d+ //; s/\n.*//; say "$k, $_"; }' mission.txt
Mission 1 Codes, 3 Star Rank - Mission 1-1
Mission 1 Codes, 3 Star Rank - Mission 1-2
Mission 2 Codes, 3 Star Rank - Mission 2-1
Mission 3 Codes, 3 Star Rank - Mission 3-1
作为文件:
use strict;
use warnings;
use feature 'say';
$/ = '';
my $key;
while (<DATA>) {
chomp;
if (s/^CAT //) {
$key = $_;
} else {
s/CODE \d+ //;
s/\n.*//;
say "$key, $_";
}
}
关于regex - 将类别与代码名称组合[DS代码格式],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75087972/