是否有一个 Bash 函数允许我在它们具有相同的第一个单词时从文件中分离/删除/隔离行



我有一个这样的文本文件:

id ; lorem ipsum  fgdg df gdg
id ; lorem ipsum  fgdg df gdg
id ; lorem ipsum  fgdg df gdg
id ; lorem ipsum  fgdg df gdg
id ; lorem ipsum  fgdg df gdg

如果 2 id 相似,我想分开到 2 id 相似的行和唯一的行。

uniquefile包含具有唯一 ID 的行。 notuniquefile包含没有行的行。

我已经找到了一种方法来几乎做到这一点,但只能用第一个词。基本上,它只是隔离id并删除行的其余部分。

命令 1:隔离唯一 id(但缺少该行(:

awk -F ";" '{!seen[$1]++};END{for(i in seen) if(seen[i]==1)print i }' originfile >> uniquefile

命令 2:隔离不唯一的 id(但缺少该行并丢失可能因行而异的"lorem ipsum"内容(:

awk -F ":" '{!seen[$1]++;!ligne$0};END{for(i in seen) if(seen[i]>1)print i  }' originfile >> notuniquefile

所以在一个完美的世界里,我希望你帮助我获得这种类型的结果:

originfile

1 ; toto
2 ; toto
3 ; toto
3 ; titi
4 ; titi

uniquefile

1 ; toto
2 ; toto
4 ; titi

notuniquefile

3 ; toto
3 ; titi

祝你今天开心。

另一种只有两个 unix 命令的方法,如果您的 id 字段始终具有相同的长度,则可以使用(假设它们的长度为一个字符,就像在我的测试数据中一样,但它当然也适用于更长的字段(:

# feed the testfile.txt sorted to uniq
# -w means: only compare the first 1 character of each line
# -D means: output only duplicate lines (fully not just one per group)
sort testfile.txt | uniq -w 1 -D > duplicates.txt
# then filter out all duplicate lines from the text file
# to just let the unique files slip through
# -v means: negate the pattern
# -F means: use fixed strings instead of regex
# -f means: load the patterns from a file
grep -v -F -f duplicates.txt testfile.txt > unique.txt

输出是(与我的另一篇文章中使用的输入行相同(:

$uniq -w 2 -D  testfile.txt 
2;line B
2;line C
3;line D
3;line E
3;line F

和:

$ grep -v -F -f duplicates.txt testfile.txt 
1;line A
4;line G

顺便说一句,如果你想避免grep,你也可以存储排序的输出(比如说在sorted_file.txt中(并将第二行替换为

uniq -w 1 -u sorted_file.txt > unique.txt

其中,-w后面的数字是 id 字段的长度(以字符为单位(。

未经测试:处理文件两次:第一次计算 ID,第二次决定在何处打印记录:

awk -F';' '
    NR == FNR      {count[$1]++; next}
    count[$1] == 1 {print > "uniquefile"}
    count[$1]  > 1 {print > "nonuniquefile"}
' file file

下面是一个执行此操作的小 Python 脚本:

#!/usr/bin/env python3
import sys
unique_markers = []
unique_lines = []
nonunique_markers = set()
for line in sys.stdin:
  marker = line.split(' ')[0]
  if marker in nonunique_markers:
    # found a line which is not unique
    print(line, end='', file=sys.stderr)
  elif marker in unique_markers:
    # found a double
    index = unique_markers.index(marker)
    print(unique_lines[index], end='', file=sys.stderr)
    print(line, end='', file=sys.stderr)
    del unique_markers[index]
    del unique_lines[index]
    nonunique_markers.add(marker)
  else:
    # marker not known yet
    unique_markers.append(marker)
    unique_lines.append(line)
for line in unique_lines:
  print(line, end='', file=sys.stdout)

不是一个纯粹的外壳解决方案(恕我直言,这将很麻烦且难以维护(,但也许它可以帮助您。

这样称呼它:

separate_uniq.py < original.txt > uniq.txt 2> nonuniq.txt

使用纯 bash 脚本,您可以像这样操作:

duplicate_file="duplicates.txt"
unique_file="unique.txt"
file="${unique_file}"
rm $duplicate_file $unique_file
last_id=""
cat testfile.txt | sort | ( 
    while IFS=";" read id line ; do
      echo $id
      if [[ "${last_id}" != "" ]] ; then
          if [[ "${last_id}" != "${id}" ]] ; then
             echo "${last_id};${last_line}" >> "${file}"
             file="${unique_file}"
          else
             file="${duplicate_file}"
             echo "${last_id};${last_line}" >> "${file}"
          fi
      fi
      last_line="${line}"
      last_id="${id}"
    done
    echo "${last_id};${last_line}" >> "${file}"
)

输入文件为:

1;line A
2;line B
2;line C
3;line D
3;line E
3;line F
4;line G

它输出:

$ cat duplicates.txt 
2;line B
2;line C
3;line D
3;line E
3;line F
work$ cat unique.txt 
1;line A
4;line G

相关内容

最新更新