【问题标题】:replace in multiline - refer to content for replacement多行替换 - 参考替换内容
【发布时间】:2014-05-30 14:55:08
【问题描述】:
我需要以下物品:
输入:
NAME-LIST:
name1
<any text>
name_to_be_changed;
NAME-LIST:
name3
<any text>
name_to_be_changed;
输出:用块中的名字替换“name_to_be_changed”
NAME-LIST:
name1
<any text>
name1;
NAME-LIST:
name3
<any text>
name3;
结果:
我更喜欢 perl 单行:-)
【问题讨论】:
标签:
regex
perl
reference
multiline
【解决方案1】:
我建议使用类似于 Sam 已经发布的搜索表达式:
(NAME-LIST:[\t ]*[\r\n]+)([^\r\n]+)([\r\n]+[^\r\n]*[\r\n]+)name_to_be_changed;
替换字符串为\1\2\3\2; 或$1$2$3$2;
每对开始和结束圆括号指定一个标记组。搜索表达式中有三个这样的标记组。
[\t ]* 使得在固定字符串NAME-LIST: 之后在块的第一行末尾可能有尾随空格或制表符。
[\r\n]+ 匹配 1 个或多个回车符或换行符。这类似于 Sam 使用的 \v,但不匹配其他垂直空格,如换页。
[^\r\n]+ 匹配 1 个或多个字符,无论是回车还是换行。这就像.,如果点的匹配行为被定义为匹配除行终止符之外的所有字符。
[^\r\n]* 匹配 0 个或多个字符,无论是回车还是换行。所以<any text> 也可以完全没有文本,这意味着第三行也可以是空行。
标记组中的表达式找到的 3 个字符串分别被 \1、\2 和 \3 反向引用 $1、$2 和 $3,其中只有第二个被反向引用两次以复制第 2 行到第 4 行的字符串,其他 3 行保持不变。
【解决方案2】:
使用 perl 单行代码
perl -00 -pe 's/NAMELIST:\n(.*)\n.*\n\K.*/$1/' file.txt
说明:
开关:
-
-00:段落模式
-
-p:为输入文件中的每一行创建一个while(<>){...; print} 循环。
-
-e:告诉perl 在命令行上执行代码。
【解决方案3】:
首先感谢您的意见...
很遗憾,我无法使用您建议的两种解决方案,但我找到了自己的解决方案:
perl -00 -pe 's/(NAME-LIST:\s+)(\w+)(.*?)\w+;/$1$2$3$2;/gs'
\s+ = 1 个或多个空格(空格、换行符、制表符...)
\w+ = 1 个或多个字母数字(如单词或数字)
重要的是/gs
g = global(替换不止一次,否则只会替换第一个名字)
s = 视为单行