如果末尾没有 S 的重复项位于同一列表中,如何删除以字母 S 结尾的单词?

如果末尾没有 S 的重复项位于同一列表中,如何删除以字母 S 结尾的单词?

我有一大堆单词。许多单词的不同只是因为它们末尾有字母 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

相关内容