RegEx使用TextWrangler删除重复的行开始

时间:2014-08-14 00:40:15

标签: regex replace textwrangler

试图转

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 我想知道,是否有优雅(例如:一种搜索模式,一种替换,一次运行)解决方案。

另一方面,我可能无法提出正确的问题来搜索网络。如果你知道的更好,请指出我正确的方向。

保持其余行对齐当然是糖果......

感谢您的时间。

6 个答案:

答案 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_]

  • shorthand
  • (.*\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

  • 结果将包含一些空行,但我确定,您可以解决这个问题......; - )

DEMO 1

但是,由于我不是超大规模正则表达的粉丝 - 而且对于你有更多潜在匹配的情况 - 我更喜欢这样的解决方案:

DEMO 2

答案 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)