我有一大堆单词。许多单词的不同只是因为它们末尾有字母 s。如果列表中的一个单词与列表中的另一个单词完全相同,除了其中一个单词以字母 s 结尾之外,我想删除以 s 结尾的重复单词。我还想在不必对列表进行排序的情况下完成此操作,以便我可以保持单词的当前位置。
输入示例:
frog
dogs
cats
cat
dog
frogs
catfish
octopus
示例输出:
frog
cat
dog
catfish
octopus
答案1
使用 awk 并读取文件两次。将所有变量保存在末尾带有 s 的数组中。检查第二次运行中每一行的数组,如果该行不在数组中则打印。
awk 'FNR==NR{a[$0 "s"]++;next}!($0 in a)' file.txt file.txt
要使用更少的内存,你也可以这样做
awk 'FNR==NR{!/s$/ && a[$0 "s"]++;next}!($0 in a)' file.txt file.txt
答案2
您可以通过多种方式执行此操作,例如,最简单的方法是对数据进行排序并比较相邻行:
sort foo |awk '{ if ( plural[$1] == "" ) print; plural[$1 "s"] = 1; }'
给定输入
frog
dogs
cats
catfish
cat
dog
frogs
输出
cat
catfish
dog
frog
不排序:
#!/bin/sh
awk 'BEGIN { count=0; }
{
words[count++] = $1;
plurals[$1 "s"] = $1;
}
END {
for ( n = 0; n < count; ++n) {
if ( plurals[words[n]] == "")
print words[n];
}
}
' <foo
输出:
frog
catfish
cat
dog
答案3
使用 bash 脚本:
#!/bin/bash
readarray -t mylist
# compare each item on the list with a new list created by appending `s'
# to each item of the original list
for i in "${mylist[@]}"; do
for j in "${mylist[@]/%/s}"; do
[[ "$i" == "$j" ]] && continue 2
done
echo "$i"
done
该列表是从标准输入读取的。这是一个测试运行:
$ cat file1
frog
dogs
cats
cat
dog
frogs
catfish
$ ./remove-s.sh < file1
frog
cat
dog
catfish
答案4
过度使用 grep -f
(从文件中获取模式)选项:
grep 's$' input | # output: all lines ending with s
sed -e 's/s$//' | # those same entries, minus the s
grep -F -x -f input | # the entries whose plurals appear
sed -e 's/$/s/' | # the plurals to remove
grep -F -x -v -f - input