我有一个以下格式的文本文件
[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
更新
我没有包含编程语言或工具,所以这里列出了可能性
对包括非正则表达式在内的任何其他建议开放。
答案 0 :(得分:3)
是的,你可以这样做。首先,您必须捕获以下正则表达式
\[(Section\d+)\]\n(.+?\n)|(?:.*?\n)\[Section\d+\]
应捕获您的部分标签以及要将其应用到的所有行。之后,应该是简单的搅拌连接
<强> Regexplanation 强>
() : 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
答案 1 :(得分:2)
这是一个Vim解决方案 - 只需打开文件并运行此命令:
:g/^\[.*\]$/ s/^\[// | s/\]$/:/ | d | ,/\n$/ normal PJ
这将选择截面标题行,将每个标题行转换为所需的形式,以便为该部分中的其他行添加前缀,删除标题行,并将其插入到该部分中所有其他行的开头。
详细说明:
:g//
选择文件中与模式匹配的行,并将以下命令应用于每个行。在这种情况下,模式匹配从[
开始并结束]
。:s///
删除了开头[
,第二个]
将结束:
更改为|
。没有必要添加尾随空格,因为连接行(见下文)将会这样做。:
分开多个:g//
命令,允许在初始:d
范围内执行多项操作。,
删除该行。这也将它存储在可以粘贴的寄存器中。这意味着'当前'行现在是该部分中的第一个属性行。,
定义范围。\n
。$
执行此操作,匹配行尾的换行符并将模式超过它,转到下一行(如果有的话)。如果该点是一行的末尾,与\n
匹配,那么必须有一个空白行(因为在,/\n$/
之后有另一个行尾)或者我们在文件的结尾。:put!
定义了需要加前缀的行范围。:join
会将最近删除的行插入当前的行之前,使刚插入的行成为当前行,然后:put
将该行与下一行连接,插入一个空格它们之间。我们希望为该范围内的每一行做到这一点。:g//
没有范围,只是一条线。通常,要将命令应用于范围中的每一行,可以使用:g//
。但是在这里我们已经在:normal
命令中了,它们不能嵌套。P
将指定的正常模式击键应用于范围中的每一行。在正常正常模式下按:put!
与J
命令相同,:join
与,/\n$/ normal PJ
相同。:normal
表示对于从当前到空白行(或文件末尾)之前的每行的每一行,将最近删除的前缀粘贴到它上面,然后将现有行加入到结尾前缀。|
不能跟随另一个命令,因为任何:normal
都将被解释为普通模式击键而不是命令分隔符。因此,通常在命令序列中使用:exe
需要将其包装在:normal
中。但是在这种情况下:g//
是我们想要做的最后一件事,所以它可以保留在命令末尾。答案 2 :(得分:1)
这可以通过单行完成:
perl -F"\n" -00 -anwE '$h = shift @F;
$h =~ s/^\[|\]$//g;
say "$h: $_" for @F;
say $/;' paragraph.txt
使用此代码,我们使用段落模式从文件中读取行块,在新行上自动分割每个块,然后取消块的第一行,清理它并将其用作生成的打印中的标题({ {1}})。
say
将输入记录分隔符设置为空字符串以启用段落模式,即读取直到下一个双换行符。-00
自动将每行输入分为-a
@F
开关允许我们将换行符设置为autosplit -F
与-E
类似,但启用了-e
代码在脚本形式中如下所示:
say
答案 3 :(得分:0)
此正则表达式捕获组中的值:
\[(?<Section>.*?)\]\r\n(?<p1>property\d)\s=\s(?<v1>value\d)\r\n(?<p2>property\d)\s=\s(?<v2>value\d)
这个用于替换前面的捕获:
${Section} : ${p1} = ${v1}
${Section} : ${p2} = ${v2}
Expresso工具的结果是:
第1节:property1 = value1
第1节:property2 = value2第2节:property1 = value1
第2节:property2 = value2
必须对其进行优化以使其成为通用
答案 4 :(得分:0)
尝试一下这个Perl单线的内容:
perl -n -wE 'if (/^\[(\w+)\]$/) { $section = $1; } else { s/^(?=\S)/$section: /; print; }' yourfile.txt
-n
让perl
一次处理文件的每一行。如果该行看起来像一个部分标题,那么它将存储该部分名称以供将来使用。否则,它会将先前存储的部分名称添加到以可打印字符开头的任何行,然后打印该行。
答案 5 :(得分:0)
这是使用perl <scriptName> <dataFile>
从命令行运行的另一个选项:
use warnings;
use strict;
my $section;
while (<>) {
if (/^\[(Section[^\]]*)\]$/) {
$section = $1;
next;
}
print /\S/ ? "$section: $_" : $_;
}