Linux

刪除特定行的重複項,僅保留每個行的第一次出現而不觸及其他未指定的重複項

  • January 2, 2022

我正在嘗試編輯包含多個重複項的文本文件。目標是僅保留字元串的第一個匹配項,並刪除同一字元串的其餘重複行。

在範例文件中

* 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 One-Liners 保持方便

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

shell - 如何刪除文件中的重複行而不在Unix中對其進行排序 - Thinbug

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

不加選擇地刪除每個重複項。

我嘗試使用這些解決方案的變體以及sed循環格式的 GNU,例如

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 等替代解決方案持開放態度,只需告訴我函式/庫名稱是什麼,我正在那裡搜尋.

謝謝。

您可以簡單地修改 awk!a[$0]++範式以使遞增模式依賴:

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

在 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

引用自:https://unix.stackexchange.com/questions/684387