我有:
constant1apple_____constant2asdfkjo___constant3
constant1apple_____constant2fdlkjef___constant3
constant1watermelonconstant2sdlfkeio__constant3
constant1banana____constant2asdfoie___constant3
constant1apple_____constant2soeivmn___constant3
constant1orange____constant2vjflkdslj_constant3
constant1watermelonconstant2xcvlvdiosnconstant3
constant1orange____constant2wieonvow__constant3
constant1apple_____constant2woemnivoiwconstant3
我只想保留第一次出现水果名称的行
输出应该是这样的:
constant1apple_____constant2asdfkjo___constant3
constant1watermelonconstant2sdlfkeio__constant3
constant1banana____constant2asdfoie___constant3
constant1orange____constant2vjflkdslj_constant3
重要笔记:
水果名称可以是任何我不知道的名字,但它们的长度都相同
水果名称后面的随机字符串可以是任意内容,但也要具有特定的长度
不知道该怎么做
答案1
使用 awk(或 perl,或大多数具有关联数组的其他语言)来做到这一点会更容易一些:
awk '!seen[substr($0, 10, 10)]++' input.txt
awk '{ fruit = substr($0, 10, 10); if (!seen[fruit]++) print }' input.txt
(awk 脚本的结构如下:match1 {code1} match2 {code2} ...
第一个变体仅指定匹配条件但不指定代码,使用隐式默认值{print;}
;第二个变体执行相反的操作但实现相同的目的。无论哪种方式,都更容易使用。)
这seen
是一个关联数组(一个字典/哈希表),用于计算第二个字段到目前为止被看到的次数。对于每一行,seen[x]++
增加保存的值seen[x]
并同时返回上一个值。如果上一个值为 0,则表示水果第一次被看到。
在这个版本中,substr(input, start, count)
用于从 $0(代表整行)中提取 10 个字符,从第 10 个字符开始。(在之前的版本中,数组键是$2
第二个以空格分隔的列。)
awk 运行良好,但取决于您计划进行多少过滤(如果不仅仅是提取唯一的第二列),最好从更通用的语言开始:
#!/usr/bin/env python3
import sys
seen = set()
for line in sys.stdin:
fruit = line[9:19]
if fruit not in seen:
seen.add(fruit)
sys.stdout.write(line)
或者,如果可以安全地重新排序名称,则可以使用uniq
它们来重复数据删除:
cat input.txt | sort | uniq --skip-chars=9 --check-chars=10
如果你只需要水果名称本身,而忽略其余部分,你可以通过提取列来实现第一的并使用uniq
剩下的:
cat input.txt | cut -c 10-19 | sort | uniq
cat input.txt | sed -r 's/^.{9}(.{10}).*/\1/' | sort | uniq