lis*_*tor 4 tabs space match width perl6
我有一个非常非常大的文本文件,我正在使用具有各种大小的缩进的行.那些可接受的行具有12个字符宽度的缩进,这些缩进是由制表符和空格的组合创建的.现在我想得到所有没有12个字符宽度缩进的行,并且这些行具有从制表符和空格字符组合的0到11个字符宽度的缩进.
if $badLine !~~ m/ ^^ [\s ** 12 ||
\t \s ** 4 ||
\s \t \s ** 3 ] / { say $badLine; }
Run Code Online (Sandbox Code Playgroud)
但问题是,当您使用文字处理器处理文本文件时,按Tab键可以为您提供0到8 space-char-width的任何位置以填补空白.什么是一种聪明的方法来获得所有那些没有12个字符宽度缩进的不可接受的行?
谢谢.
对于缩进宽度为12,假设制表位于0,8,16等位置:
for $input.lines {
.say if not /
^ # start of line
[" " ** 8 || " " ** 0..7 \t] # whitespace up to first tab stop
[" " ** 4] # whitespace up to position 12
[\S | $] # non-space character or end of line
/;
}
Run Code Online (Sandbox Code Playgroud)
说明:
要从行的开头(位置0)到第一个制表位(位置8),我们需要匹配两种可能性:
从制表位(位置8)到缩进目标(位置12)的唯一方法是4个空格.(标签会跳过目标到位置16的下一个标签位置.)
锚定到线的起点以及压痕后的任何内容都很重要,这样我们就不会意外地匹配较长压痕的一部分.
缩进匹配可以分解为可以处理任意宽度的参数化命名标记:
my token indent ($width) {
[" " ** 8 || " " ** 0..7 \t] ** {$width div 8}
" " ** {$width % 8}
}
.say if not /^ <indent(12)> [\S | $]/ for $input.lines;
Run Code Online (Sandbox Code Playgroud)
说明:
使用与上面相同的表达式来到达第一个制表位,但现在根据需要重复多次以到达目标之前的最后一个制表位.($width div 8总计时间,div整数除法运算符在哪里).
无论最后一个制表位与目标之间的距离是什么,都必须填充空格.($width % 8空格,%模数运算符在哪里.)
上例中的标记假定它在标签停止位置(例如行的开头)开始匹配.它可以进一步推广以匹配给定宽度的制表符和空格,无论您在哪个行中调用它:
my token indent ($width) {
:my ($before-first-stop, $numer-of-stops, $after-last-stop);
{
$before-first-stop = min $width, 8 - $/.from % 8;
$numer-of-stops = ($width - $before-first-stop) div 8;
$after-last-stop = ($width - $before-first-stop) % 8;
}
[" " ** {$before-first-stop} || " " ** {^$before-first-stop} \t]
[" " ** 8 || " " ** 0..7 \t] ** {$numer-of-stops}
" " ** {$after-last-stop}
}
Run Code Online (Sandbox Code Playgroud)
说明:
与之前相同的原则,除了现在我们首先需要匹配尽可能多的空格以从字符串中的当前位置到其后面的第一个制表位.
字符串中的当前位置由$/.from; 其余的是简单的算术.
在令牌中声明并使用了一些词法变量(带有希望描述性的名称),以使代码更容易理解.