删除特定行的重复项,仅保留每个行的第一次出现,而不触及其他未指定的重复项

删除特定行的重复项,仅保留每个行的第一次出现,而不触及其他未指定的重复项

我正在尝试编辑包含多个重复项的文本文件。目标是仅保留字符串的第一个匹配项并删除同一字符串的其余重复行。

在示例文件中

* Title 1
** Subtitle 01
#+begin_src
  Line 001
  Line 002
#+end_src

* Title 1
** Subtitle 02
#+begin_src
  Line 001
  Line 002
#+end_src

* Title 2
** Subtitle 01
#+begin_src
  Line 001
  Line 002
#+end_src

* Title 2
** Subtitle 02
#+begin_src
  Line 001
  Line 002
#+end_src

我想各保留* Title N一个保留所有其他不相关/未指定的重复行在文件上。所以结果是:

* Title 1
** Subtitle 01
#+begin_src
  Line 001
  Line 002
#+end_src

** Subtitle 02
#+begin_src
  Line 001
  Line 002
#+end_src

* Title 2
** Subtitle 01
#+begin_src
  Line 001
  Line 002
#+end_src

** Subtitle 02
#+begin_src
  Line 001
  Line 002
#+end_src

删除重复项的传统解决方案如

uniq file.txt

方便使用的有用 AWK 单行代码

awk '!a[$0]++' contents.txt

shell - 如何删除文件中的重复行而不在 Unix 中对其进行排序 - Thinbug

perl -ne 'print if ! $x{$_}++' file

不加区别地删除所有重复项。

我尝试使用这些解决方案的变体以及 GNU 的sed循环格式,例如

duplicateLines=$(grep -E "^\* .*" file.org | uniq)
  printf '%s\n' "$duplicateLines" | while read -r line; do
  sed "s/$line//g2" file.org
done

没有成功。我不介意绝对性能,因此进行多次迭代(例如sed 在循环内调用一次删除一个指定的字符串)是没有问题的。

任何见解将不胜感激。

如果能够在 shell 脚本中执行此操作,那就太好了,但我愿意接受其他解决方案,例如 Python、C、Java 等,只需告诉我函数/库名称是什么,我就会在那里搜索它。

谢谢。

答案1

您可以简单地修改 awk!a[$0]++范例以使递增模式依赖于:

awk '!a[$0]; /^\* Title/{a[$0]++}' file

答案2

在 awk 中,我们惯用使用一个名为 的数组seen[]来区分字符串的第一次出现和后续出现,例如:

awk '!seen[$0]++'

只会输出每行的第一次出现。

在您的情况下,您只想在当前行以* Title以下内容开头时使用它:

$ awk '!( /^\* Title/ && seen[$0]++ )' file
* Title 1
** Subtitle 01
#+begin_src
  Line 001
  Line 002
#+end_src

** Subtitle 02
#+begin_src
  Line 001
  Line 002
#+end_src

* Title 2
** Subtitle 01
#+begin_src
  Line 001
  Line 002
#+end_src

** Subtitle 02
#+begin_src
  Line 001
  Line 002
#+end_src

相关内容