我想用制表符替换每行开头的每两个空格。我尝试了以下方法:
s/^(\s{2})+/\t/gm;
它没有用。
如果您正在逐行读取文件:
$line =~ s/\G[ ]{2}/\t/g;
如果您已吞下整个文件:
$file =~ s/(?:\G|^)[ ]{2}/\t/mg;
这个怎么样?
my $test_string = " some test stuff\ndivided to\n provide the challenge";
$test_string =~ s/^[ ]{2}/\t/gm;
print $test_string;
解释:\s
实际上不是一个单一的符号别名,而是一个字符“空白”类:它包括两者\n\
,\t
例如。如果您只想替换空格,请在正则表达式中使用空格;设置一个字符类(而不只是/^ {2}/...
对我来说更具可读性(并且不会与/x
修饰符中断)。
此外,如果您只想替换两个空格符号,则不需要使用+
量词。
更新:如果您需要替换每两个空格,我想我会改用这个:
$test_string =~ s#^((?:[ ]{2})+)#"\t" x (length($1)/2)#gme;
...或者只是 ikegami 的答案中的 \G 锚。
请记住,+
量词的意思是“一个或多个”,它应用于\s{2}
表示“正好两个空白字符”。举个简单的例子,考虑一个创建零到十个空格的字符串并尝试将它们与类似模式匹配的程序。
#! /usr/bin/env perl
use strict;
use warnings;
for (0 .. 10) {
$_ = " " x $_;
printf "%-13s %s\n", "[$_]:", /^(\s{2})+$/ ? "match!" : "no match.";
}
输出:
[]:不匹配。 [ ]:不匹配。 [ ]: 匹配! [ ]:不匹配。 [ ]: 匹配! [ ]:不匹配。 [ ]: 匹配! [ ]:不匹配。 [ ]: 匹配! [ ]:不匹配。 [ ]: 匹配!
如所写,您的模式将单个 TAB 字符替换为逻辑行首的任何正偶数个空白字符。
您没有提供更广泛的代码上下文。从/m
和/g
开关的使用来看,我假设您有一些文本,可能是文件的全部内容,您希望将其作为一个整体进行操作。下面的程序使用 here-document 模拟了这种假设情况,并仅将每行的前两个空格替换为 TAB。
#! /usr/bin/env perl
use strict;
use warnings;
$_ = <<EOText;
Three
Two
Four
Five
Zero
One
EOText
s/^ /\t/mg;
# for display purposes only
s/\t/\\t/g;
print;
输出:
\t 三 \t两个 \t 四 \t 五 零 一
请注意,额外注释s///
不会保留在您的代码中。它可以在空格和 TAB 字符之间添加对比。
如果这是你的程序的唯一目的,它就变成了一个简单的单行。要使用修改后的内容创建新文件,请使用
$ perl -pe 's/^ /\t/' 输入文件>输出文件
就地编辑看起来像
$ perl -i.bak -pe 's/^ /\t/' 输入文件
作为替代解决方案,/m
您可以在没有修饰符的情况下使用正向后视。这种方法对于需要检查其他内容的情况很有用,而不仅仅是行首,所以当\m
修饰符无济于事>>
$_ = " 123\n 456\n 789";
s/(?:(?<=^)|(?<=\n))\s{2}/\t/g;
print $_;
在上面的示例代码中,字符串开头或换行符后面的每个/g
双空格都被替换为 tab 。\s{2}
(?<=^)
(?: .. | .. )
(?<=\n)
\t