Javascript 使用正则表达式为每行添加节标题
我有一个以下格式的文本文件Javascript 使用正则表达式为每行添加节标题,javascript,regex,perl,vim,Javascript,Regex,Perl,Vim,我有一个以下格式的文本文件 [Section1] property1 = value1 property2 = value2 [Section2] property1 = value1 property2 = value2 一个例子 [Section foo] foo = 1 bar = "whatever" 有没有什么方法可以像这样使用正则表达式将章节标题添加到每一行 Section1: property1 = value1 Section1: property2 = value2 S
[Section1]
property1 = value1
property2 = value2
[Section2]
property1 = value1
property2 = value2
一个例子
[Section foo]
foo = 1
bar = "whatever"
有没有什么方法可以像这样使用正则表达式将章节标题添加到每一行
Section1: property1 = value1
Section1: property2 = value2
Section2: property1 = value1
Section2: property2 = value2
更新
我没有包括编程语言或工具,所以这里有一个可能性列表
欢迎任何其他建议,包括非正则表达式。是的,您可以这样做。首先,您必须捕获以下正则表达式
\[(Section\d+)\]\n(.+?\n)|(?:.*?\n)\[Section\d+\]
它应该捕获您的分区标签,以及您要将其应用到的所有行。之后,应该是简单的搅拌浓缩
regexplainion
() : a capturing group
(?:..) : non-capturing group
\d+ : 1 or more digits
.+?\n : 1 or more characters and newline(the '?' means it's non-greedy)
.*?\n : 0 or more characters and newline
此正则表达式捕获组中的值:
\[(?<Section>.*?)\]\r\n(?<p1>property\d)\s=\s(?<v1>value\d)\r\n(?<p2>property\d)\s=\s(?<v2>value\d)
Expresso工具中的结果是:
第1部分:属性1=值1第1节:属性2=值2 第2节:属性1=值1
第2节:属性2=值2
必须对其进行优化,使其具有通用性请尝试使用以下Perl one liner:
perl -n -wE 'if (/^\[(\w+)\]$/) { $section = $1; } else { s/^(?=\S)/$section: /; print; }' yourfile.txt
perl -F"\n" -00 -anwE '$h = shift @F;
$h =~ s/^\[|\]$//g;
say "$h: $_" for @F;
say $/;' paragraph.txt
-n
使perl
一次处理文件的每一行。如果该行看起来像一个节标题,那么它将存储节名称以备将来使用。否则,它会将先前存储的节名前置到以可打印字符开头的任何行,然后打印该行。这可以通过一行完成:
perl -n -wE 'if (/^\[(\w+)\]$/) { $section = $1; } else { s/^(?=\S)/$section: /; print; }' yourfile.txt
perl -F"\n" -00 -anwE '$h = shift @F;
$h =~ s/^\[|\]$//g;
say "$h: $_" for @F;
say $/;' paragraph.txt
在这段代码中,我们使用段落模式从文件中读取行块,在换行符上自动拆分每个行块,然后去掉块的第一行,将其清理干净,并将其用作最终打印的标题(比如说
)
将输入记录分隔符设置为空字符串,以启用段落模式,即读取到下一个双换行符-00
自动将每行输入拆分为-a
@F
开关允许我们将换行符设置为自动拆分的分隔符-F
与-E
类似,但启用功能,如-E
比如说
use warnings;
use strict;
$/ = ""; # paragraph mode, read until "\n\n"
use feature 'say'; # enable 'say'
while (<>) {
my @F = split /\n/;
my $h = shift @F;
$h =~ s/^\[|\]$//g; # clean up lines
say "$h: $_" for @F;
say $/; # print paragraph ending
}
使用警告;
严格使用;
$/ = ""; # 段落模式,读取到“\n\n”
使用功能“说”;#启用“说”
而{
my@F=split/\n/;
my$h=shift@F;
$h=~s/^\[|\]$//g;#清理线路
对@F说“$h:$\”;
说$/#打印段落结尾
}
这里是另一个使用perl从命令行运行的选项:
使用警告;
严格使用;
我的$section;
而(){
如果(/^\[(第[^\]]*)\]$/){
$section=$1;
下一个
}
打印/\S/?“$节:$\:$\;
}
这里有一个Vim解决方案-只需打开文件并运行以下命令:
:g/^\[.*\]$/ s/^\[// | s/\]$/:/ | d | ,/\n$/ normal PJ
这将选择节标题行,将每一行转换为该节中其他行的前缀所需形式,删除标题行,并将其插入节中所有其他行的开头
详细内容:
:g//
选择文件中与模式匹配的行,并将以下命令应用于每一行。在这种情况下,模式匹配以[
和]
结尾的行
- 第一个
:s//
删除了打开的[
,第二个]
更改为关闭的:
。没有必要添加尾随空格,因为连接行(请参见下文)可以做到这一点
|
将多个:
命令分开,允许在初始:g/
范围内执行多个操作
:d
删除该行。这也会将其存储在寄存器中,以便粘贴。这意味着“当前”线现在是该部分的第一条建筑红线
- 前缀需要添加到节中的所有行中<代码>,
定义一个范围
,
之前不需要任何内容\n
就是这样做的,它匹配一行末尾的换行符,并将模式经过它,转到下一行(如果有)。如果该点是一行的结尾,与$
匹配,则后面必须有一个空行(因为在\n
后面紧跟着另一行结尾),否则我们就在文件的末尾:放
将在当前行的上方插入最近删除的行,使刚插入的行成为当前行,然后:join
将该行与下一行连接,在它们之间插入空格。我们希望对范围内的每一行都这样做:put
不取范围,只取一行。通常,要对某一范围内的每一行应用命令,可以使用:g/
。但是这里我们已经在一个:g/
命令中,它们不能嵌套:normal
将指定的normal模式按键应用于范围内的每一行。在正常模式下按P
与相同:put
命令,并且J
与:join
相同:normal
后面不能跟另一个命令,因为任何|
都会被解释为普通模式的击键,而不是命令分隔符。所以一般来说,美国