试图转
a: 1, 2, 3
a: a, b, v
b: 5, 6, 7
b: 10, 1543, 1345
b: e, fe, sdf
cd: asdf, asdfas dfasdfa,asdfasdfa,afdsfa sdf
e1: asdfas, dafasd, adsf, asdfasd
e1: 1, 3, 2
e1: 9, 8, 7, 6
到
a: 1, 2, 3
a, b, v
b: 5, 6, 7
10, 1543, 1345
e, fe, sdf
cd: asdf, asdfas dfasdfa,asdfasdfa,afdsfa sdf
e1: asdfas, dafasd, adsf, asdfasd
1, 3, 2
9, 8, 7, 6
因此,线条已排序。如果连续行以相同的字符序列开始,直到/包括某些分隔符(此处为冒号(及其后面的空白)),则只应保留第一个实例 - 应该是所有行的其余部分。 从相同的字符序列开始,最多可能有十几(一半)行。 输入大约有4,500行...
在TextWrangler中尝试过。
虽然搜索模式
^([[:alnum:]]+): (.+)\r((\1:) (.+)\r)*
匹配正确,无法替换
\1:\t\2\r\t\3\r
,也不
\1:\t\2\r\t\4\r
让我接近我正在寻找的东西。
搜索模式
^(.+): (.+)\r((?<=\1:) (.+)\r)*
被拒绝,因为后卫不是固定长度。 - 不确定,无论如何它都会朝着正确的方向前进。
看着 How to merge lines that start with the same items in a text file 我想知道,是否有优雅(例如:一种搜索模式,一种替换,一次运行)解决方案。
另一方面,我可能无法提出正确的问题来搜索网络。如果你知道的更好,请指出我正确的方向。
保持其余行对齐当然是糖果......
感谢您的时间。
答案 0 :(得分:6)
作为变长lookbehind的变通方法:PCRE允许可变长度的替代
PCRE在外观方面并不完全兼容Perl。虽然Perl要求lookbehind内部的替代品具有相同的长度,但PCRE允许可变长度的替代品。
需要为每个最大前缀长度字符添加管道的想法:
(?<=(\w\w:)|(\w:)) (.*\n?)\1?\2?
并替换为\t\3
。见test at regex101。捕捉后视内部对于不消耗/不跳过匹配很重要。相同的模式变量eg .NET:(?<=(\w+:)) (.*\n?)\1?
(?<=(\w\w:)|(\w:))
前两个capture groups内窥镜用于捕获前缀:两个或一个字符后跟一个冒号。 \w
是[A-Za-z0-9_]
(.*\n?)
第三个捕获组,用于填充前缀之间的内容。获取最后一场比赛的可选换行符。
\1?\2?
将可选地替换相同的前缀。只能设置其中一个:\1
xor \2
。此外,冒号后的空格也将始终匹配 - 无论前缀如何。
摘要:每个前缀转换为制表符后的空格。仅当匹配当前时,以下行的前缀 要匹配和替换多个空格和标签:(?<=(\w\w:)|(\w:))[ \t]+(.*\n?)\1?\2?
答案 1 :(得分:4)
替换的问题是不确定的匹配数。限制该数量时,例如到12,你可以使用这样的正则表达式:
^([^:]+): ([^\n]+[\n]*)(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?(\1: ([^\n]+[\n]*))?
有了这个替代品:
\n\1:\t\2\t\4\t\6\t\8\t\10\t\12\t\14\t\16\t\18\t\20\t\22\t\24
说明:它基本上只包含两个子正则表达式
^([^:]+): ([^\n]+[\n]*)
=匹配组的第一行
(\1: ([^\n]+[\n]*))?
=连续行上的可选匹配项,属于同一组。您必须根据需要经常复制此正则表达式以匹配所有行(即在此情况下为12x)。如果所有替换都没有足够匹配,则?
(=可选)匹配不会给您错误。
格式问题需要替换开头的\n
结果将包含一些空行,但我确定,您可以解决这个问题......; - )
但是,由于我不是超大规模正则表达的粉丝 - 而且对于你有更多潜在匹配的情况 - 我更喜欢这样的解决方案:
合并属于同一组的所有行(如您所述:How to merge lines that start with the same items in a text file)。在这些步骤中,您可以使用唯一的内容替换组项(例如:@:
)。
将此唯一项目替换为\n\t
答案 2 :(得分:1)
下面的awk单行将做你想做的事情
awk -F: 'NR==1 {print $0} NR != 1 {if ($1 != prev) print $0; else {for (i=0; i<=length($1); ++i) printf " "; print $2;}} {prev=$1}' < input_file.txt
(将原始文本放入input_file.txt)
我相信可以编写更好的代码,但现在是时候睡觉了)
答案 3 :(得分:1)
我在Bare Bones Software Inc.的TextWrangler中尝试了你的样本,我想出了一个两遍解决方案,仅限于 n 连续行,它使用了一个标签而不是试图神奇地匹配前缀的长度。另请注意,文件的最后一行应为空行(在示例中, 6
之后添加换行符)
出于我们的目的,我会向您展示 n = 4的位置:
Find: ^([[:alnum:]]+\:)(.+\r)(?:\1(.+\r))?\1(.+)\r
Replace: \1\2\t\3\t\4\t\5\r
您可以通过在(?:\1(.+\r))?
中复制Find
并在\t\n
\r
之前添加Replace
来向任何 n 添加一个 n 其中* n *是在\r
之前的最后一个数字之后的增量。
用此替换所有内容,您可以通过以下方式进行跟进:
Find: ^\t+
Replace: \t
主要是获得你想要的结果。
答案 4 :(得分:0)
因此,除了第一个实例之外你想要替换所有其他实例,我假设您需要正则表达式来匹配除第一个之外的所有实例,因此您可以替换它们。如您所知,正则表达式无法修改或更改原始字符串,只返回特定匹配,本身可用于指定要修改的字符串部分。
我能提出的最好的正则表达式是/(\b[a-zA-Z0-9]+: )[^\n]+(?:\n|$)(?!\1)/g
。
这将捕获xx:
的每个唯一实例,并匹配它的最后一个实例。唯一的问题是它仍然匹配最后一个实例,即使它是唯一的实例。
我的结论是,我不相信你可以用正则表达式完成所有这些。我可能错了,如果有人能找到支持lookbehind和反向引用的在线正则表达式调试器,让我吧我知道,我是否可以写一个表达式来工作。我个人无法找到任何接受反向引用和后视的正则表达式调试器。在我的例子中,我使用了lookahead,因此它会检查前面是否有任何实例,如果是,则忽略当前匹配(因此它只选择最后一个实例)。
如果你真的想找到一种方法来自动化它以使其工作,使用/(\b[a-zA-Z0-9]+: )/g
匹配xx:
的每个实例,将它们全部存储在一个数组中,如果有重复,运行特定的原始正则表达式继续修剪它直到没有更多的重复。您可以再次使用它来存储所有唯一的实例并以某种方式利用它。
希望这有助于或澄清您的问题,如果不是,请道歉。
答案 5 :(得分:-1)
没有Textwrangler进行测试,但我在其他Regex工具中测试过,它运行良好,请尝试:
(?<=(?:(?:.+\n)|^)(\w+?:).+\n)\1(?=\s)