【问题标题】:Regex for removing repeating numbers on different lines [duplicate]用于删除不同行上的重复数字的正则表达式[重复]
【发布时间】:2011-09-28 20:58:30
【问题描述】:

这可能很简单,但我想不通:

我有一个随机数(可以是 1、2、3 或 4 位数字) 它在第二行重复:

2131
2131

如何删除第一个数字?

编辑:对不起,我没有更好地解释它。这些行位于纯文本文件中。我使用 BBEdit 作为我的编辑器。实际文件看起来像这样(只有 app.10.000 行):

336
336
rinde
337
337
diving
338
338
graffiti
339
339
forest
340
340
mountain

如果可能,结果应如下所示:

336 - rinde
337 - diving
338 - graffiti
339 - forest
340 - mountain

【问题讨论】:

  • 在第二行或第二列重复?在您的示例中,它是第二列。请使用代码标签。
  • 什么语言?所有这些都在同一个字符串中吗?为什么必须使用正则表达式?
  • @CanSpice +1 您可以使用哪种工具/语言?这些数字在文件中吗?
  • @Kent:根据编辑,这是通过 BBEdit 的 search-n-replace 完成的,这似乎是由 PCRE 库提出的。我已经相应地重新标记了。

标签: regex pcre bbedit


【解决方案1】:

搜索:

^(\d{1,4})\n(?:\1\n)+([a-z]+$)

替换:

\1 - \2

我无权访问 BBEdit,但显然您必须检查“Grep”选项才能启用 regex search-n-replace。 (我不知道他们为什么这么称呼它,因为它似乎是由 PCRE 库提供支持的,它比 grep 强大得多。)

【讨论】:

  • +1,完成的一些信息:PCRE 没有替代功能(这可能会在即将推出的 pcre2 API 中出现),因此必须在每种工具或语言中实现; BBEdit 使用 2003 年初的一个非常旧的 PCRE 版本。
【解决方案2】:

因为你没有提到任何编程语言,工具。我假设这些数字在一个文件中。每个每行,任何重复的数字都在相邻行中。 uniq 命令可以解决你的问题:

kent$  echo "1234
dquote> 1234
dquote> 431
dquote> 431
dquote> 222
dquote> 222
dquote> 234"|uniq

1234
431
222
234

【讨论】:

  • 如果它们不在相邻线路中,您可以在uniq 之前通过sort 进行管道传输,但随后您将失去排序。订购是否重要可能是提问者无法回答的问题,但是......
  • @CanSpice OP 也从示例中提到了It's repeating on a second line,我认为它们在相邻线路中。如果没有,还有其他解决方案,例如awk/sed 可以很好地处理它,即使需要保留顺序。
【解决方案3】:

另一种方式查找:/^(\d{1,4})\n(?=\1$)/ 替换:""
修饰符mg(多行和全局)

$str =
'1234
1234
431
431
222
222
222
234
234';

$str =~ s/^(\d{1,4})\n(?=\1$)//mg;
print $str;

输出:
1234
431
222
234

添加在修改后的示例中,您可以执行以下操作:

查找:/(?=^(\d{1,4}))(?:\1\n)+\s*([^\n\d]*$)/
替换:$1 - $2
模组:/mg(多行,全局)

测试:

$str =
'
336
336
rinde
337
337
337
diving
338
338
graffiti
339
337
339
forest
340
340
mountain
';

$str =~ s/(?=^(\d{1,4}))(?:\1\n)+\s*([^\n\d]*$)/$1 - $2/mg;

print $str;

输出:
第336话
337 - 潜水
338 - 涂鸦
339
337
339 - 森林
340 - 山

Added2 - 与原始问题相比,OP 后期所需的输出格式给我留下了更深刻的印象。它有很多元素,所以无法控制自己,生成了一个过于复杂的正则表达式。

搜索:/^(\d{1,4})\n+(?:\1\n+)*\s*(?:((?:(?:\w|[^\S\n])*[a-zA-Z](?:\w|[^\S\n])*))\s*(?:\n|$)|)/
替换:$1 - $2\n
修饰符:mg (multi-line, global)

扩展-

# Find:
s{ # Find a single unique digit pattern on a line (group 1)

   ^(\d{1,4})\n+   # Grp 1, capture a digit sequence

   (?:\1\n+)*      # Optionally consume the sequence many times,
   \s*             # and whitespaces (cleanup)

   # Get the next word (group 2)
   (?:
     # Either find a valid word
       (                      # Grp2 
          (?:
             (?:\w|[^\S\n])*     # Optional \w or non-newline whitespaces
             [a-zA-Z]            # with at least one alpha character
             (?:\w|[^\S\n])*
          )
       )
       \s*                    # Consume whitespaces (cleanup),
       (?:\n|$)               # a newline
                              # or, end of string
     |
     # OR, dont find anything (clears group 2)
   )
 }

# Replace (rewrite the new block)
 {$1 - $2\n}xmg;  # modifiers expanded, multi-line, global

【讨论】:

    【解决方案4】:

    找到:

    ((\d{1,4})\r(\D{1,10}))|(\d{1,6})
    

    替换:

    \2 - \3
    

    你应该可以很容易地从那里清理它!

    【讨论】:

      【解决方案5】:

      使用正则表达式无法检测到这样的模式。

      你可以用“\n”分割字符串,然后比较。

      【讨论】:

      • 我希望来自投票者的正则表达式。
      • 查看我的答案或 CanSpice 的合适正则表达式——这是针对修改后的问题,它比原始问题更复杂。为什么你会认为这是不可能的?
      • 来自 Wikipedia “现代正则表达式库中的许多功能提供了远远超过正则语言的表达能力。例如,许多实现允许使用括号对子表达式进行分组并在同一表达式中调用它们匹配的值(反向引用)。这意味着一个模式可以匹配重复的单词字符串,如“papa”或“WikiWiki”,在形式语言理论中称为正方形。这些字符串的模式是(.*)\1。”
      • 我刚刚明白应该使用“常规语言”。有些语言可以有更强大的表达式,但它们不是正规的。换句话说,我说这个问题不能用 type-3 乔姆斯基语法来解决。 en.wikipedia.org/wiki/Chomsky_hierarchy
      • 我也有同样的怀疑:正则表达式的人格分裂再次来袭!除非他们另有说明,否则当有人在 SO 询问正则表达式时,您应该假设他们在谈论蓝领 正则表达式,而不是象牙塔 正则表达式。 :P
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-08
      • 2011-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多