Tabs perl6如何获得所有未按空格x宽度缩进的行?
我有一个非常非常大的文本文件,我正在处理这个文件,其中的行有各种大小的缩进。可接受的行具有12个字符宽度的缩进,缩进由制表符和空格组合而成。现在我想得到所有没有12个字符缩进宽度的行,这些行有0到11个字符的缩进宽度,由制表符和空格字符组合而成Tabs perl6如何获得所有未按空格x宽度缩进的行?,tabs,width,match,space,raku,Tabs,Width,Match,Space,Raku,我有一个非常非常大的文本文件,我正在处理这个文件,其中的行有各种大小的缩进。可接受的行具有12个字符宽度的缩进,缩进由制表符和空格组合而成。现在我想得到所有没有12个字符缩进宽度的行,这些行有0到11个字符的缩进宽度,由制表符和空格字符组合而成 if $badLine !~~ m/ ^^ [\s ** 12 || \t \s ** 4 || \s \t \s ** 3 ] / { say $badLine;
if $badLine !~~ m/ ^^ [\s ** 12 ||
\t \s ** 4 ||
\s \t \s ** 3 ] / { say $badLine; }
但问题是,当您使用文字处理器处理文本文件时,按tab键可以为您提供0到8个字符宽度的空间,以填补空白。有什么聪明的方法可以得到那些不可接受的没有12个字符宽度缩进的行
谢谢。假设我正确理解了您的问题(如果我没有弄糟),一种方法应该是:
# some test input
my \INPUT = qq:to/EOI/;
11s
12s
13s
\t 1t 4s
\t 1s 1t 3s
4s
\t 3s 1t 4s
\t8s 1t
EOI
# compute indentation width
sub indent-width($_) {
my $n = 0;
# iterate over characters
for .comb {
# tabs only take enough space to fill an octet
when "\t" { $n += 8 - $n % 8 }
default { ++$n }
}
$n;
}
# generate output, see below
say ?/^ :r (\h+) <?{ indent-width(~$0) == 12 }> /, " {.trim}"
for INPUT.lines;
#一些测试输入
my\INPUT=qq:to/EOI/;
11秒
12秒
13秒
\t 1t 4s
\t 1s 1t 3s
4s
\t 3s 1t 4s
\t8s 1t
意向书
#计算压痕宽度
子缩进宽度(美元){
我的$n=0;
#迭代字符
梳子{
#制表符只占用足够的空间来填充八位字节
当“\t”{$n+=8-$n%8}
默认值{++$n}
}
$n;
}
#生成输出,请参见下文
说?/^:r(\h+)宽度12
对于12的压痕宽度,假设止动块位于位置0、8、16等处:
$input.lines的{
.如果没有,就说/
^#线路起点
[“”**8 | |“”**0..7\t]#直到第一个制表位的空格
[“”**4]#空格直到位置12
[\S |$]#非空格字符或行尾
/;
}
说明:
要从行的起点(位置0)到达第一个制表位(位置8),我们需要匹配两种可能性:
- 8个空间
- 0到7个空格,后跟1个制表符。(制表符直接跳到制表位,因此它会填充空格后剩余的任何宽度。)
从止动块(位置8)到缩进目标(位置12)的唯一方法是4个空格。(一个制表符将跳过目标跳转到位置16处的下一个制表符停止点。)
锚定到行的开始,以及缩进之后的任何内容,都很重要,这样我们就不会意外地匹配较长缩进的一部分
任意宽度
压痕匹配可以分解为可处理任意宽度的参数化形状:
我的令牌缩进($width){
[**8 | |**0..7\t]**{$width div 8}
“**{$width%8}”
}
.if not/^[\S |$]/表示$input.lines;
说明:
使用与上面相同的表达式到达第一个制表位,但现在需要重复多次才能到达目标之前的最后一个制表位。($width div 8
总计次,其中为整数除法运算符)
最后一个制表位和目标之间的距离必须用空格填充。($width%8
空格,其中是模运算符。)
任意位置和宽度
上例中的标记假设它在制表符停止位置(例如行的开始)开始匹配。它可以进一步推广,以匹配给定宽度的制表符和空格,无论您在哪一行中调用它:
我的令牌缩进($width){
:my($第一站前,$站数,$最后一站后);
{
$before first stop=最小$width,8-$/。从%8开始;
$NUMBER of stops=($width-$before first stop)第8部分;
$after last stop=($width-$after first stop)%8;
}
[“***{$beforeist stop}| |”“***{^$beforeist stop}\t]
[**8 | |**0..7\t]**{$numer of stops}
“***{$after last stop}”
}
说明:
与之前的原理相同,只是现在我们首先需要匹配从字符串中的当前位置到其后的第一个制表位所需的尽可能多的空格
字符串中的当前位置由$/。from
;剩下的是简单的算术
在令牌中声明并使用了一些词汇变量(希望具有描述性名称),以使代码更易于理解
根据您的描述,\s\t\s**3
不应该不匹配,因为它只会产生11的宽度,而不是12?“0到8的任何空格字符宽度”您确定它不是1到8吗?另外,请注意\s
匹配任何空格字符,包括制表符。使用“
或”
匹配正常空格,就像我在回答中所做的那样。再次感谢你们,Christoph和smls!对于/\s\t\s**3/,第一个\s占据一个字符\t取8个字符;和\s**3占用3个字符宽度;因此,我认为它将匹配12 cha宽度。标签宽度应为1到8个字符;我错了,对不起,smls。谢谢smls!我将尝试你的代码,我需要阅读更多的Perl6文档来理解你的代码。对于['**8 | |”“**0..7\t],您能将其简化为[''**0..8 | | | \t]吗?@lisprogtor:我添加了更多解释和答案链接,希望能帮助您理解代码。谢谢Christoph!我需要阅读更多的Perl6文档来理解您的代码,但我相信它们是有效的:-)@lisprogtor:我添加了一些注释;我还添加了:r
修饰符来拒绝带有额外缩进的行。这种计数方法也可以在正则表达式中完成:/:my$h=0;^[“{++$h}|\t{$h+=8-$h%8}]+
/^ :r (\h+) <?{ indent-width(~$0) == 12 }> /