끝에 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

관련 정보