私は膨大な量の単語のコレクションを持っています。多くの単語は末尾に文字sがあるので異なります。リスト内の単語が文字sで終わる単語の1つを除いて、リスト内の他の単語とまったく同じ場合は、sで終わる重複単語を削除したいと思います。また、単語の現在位置を維持できるようにリストを並べ替える必要なく、これを行いたいと思います。
入力例:
frog
dogs
cats
cat
dog
frogs
catfish
octopus
出力例:
frog
cat
dog
catfish
octopus
答え1
awkを使用してファイルを2回読みます。最後に s がある配列にすべての変数を格納します。 2番目の実行では、各行の配列を確認し、その行が配列にない場合は印刷します。
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