문자 세트의 문자를 단 한 번만 일치시킬 수 있는 정규 표현식이 있습니까? 즉, 캐릭터가 발견되면 세트에서 제거됩니다.
grep이 이 작업을 수행할 수 없는 경우 이를 수행할 수 있는 내장 유틸리티가 있습니까?
예:
Characters to match only once: spine
입력하다:
spine
spines
spin
pine
seep
spins
산출:
spine
spin
pine
편집하다:
이 출력을 얻는 방법은 여러 가지가 있지만(아래 예 참조) 일치시키려는 각 패턴에 대해 사용자 정의 명령을 만들지 않고도 이를 달성할 수 있는 방법을 찾고 있습니다.
grep '[spine]' input_file | grep -v 's.*s' | ... | grep -v 'e.*e'
답변1
답변2
귀하의 표현에 영감을 받아 egrep을 사용하여 더 짧은 표현을 생각해 낼 수 있습니다.
egrep -v '(s.*s|p.*p|i.*i|n.*n|e.*e)' FILE
이는 다음과 같습니다.
sed /s.*s/d;/p.*p/d;/i.*i/d;/n.*n/d;/e.*e/d; FILE
다음은 입력에서 sed 명령을 자동으로 생성하는 방법입니다.
#!/bin/bash
word=$1
file=$2
expr=$(for c in $(echo $word | sed 's/./& /g'); do echo -n "/"$c".*"$c"/d;"; done);
sed $expr $file
grep을 사용하여 유사한 접근 방식을 시도했지만 쉘이 변수에서 grep 패턴을 가져오도록 설득할 수 없었지만 이를 에코하고 잘라내어 붙여넣기를 통해 결과를 삽입하면 명령이 작동합니다.
expr="'("$(for c in $(echo $wort | sed 's/./& /g'); do echo -n $c".*"$c"|"; done)
egrep -v ${expr/%|/)\'} FILE
# doesn't work, filters nothing, whole file is printed
# check:
echo egrep -v $(echo $exp) FILE
egrep -v '(s.*s|p.*p|i.*i|n.*n|e.*e)' FILE
# manually:
egrep -v '(s.*s|p.*p|i.*i|n.*n|e.*e)' FILE
spine
spin
pine
제가 실수를 했을 수도 있고, 변수 확장에 실수를 했을 수도 있습니다.
답변3
이는 문자열이 무엇인지 미리 알 필요가 없는 비정규식 접근 방식입니다. 가장 효율적이라고 말할 수는 없지만 내 요구 사항에는 충분히 빠릅니다.
$ (echo a;echo abc;echo aabc;echo def;echo two words;echo one pair) | awk '
> {
> split($0,a,"");
> n=asort(a);
> for(i=1;i<=n;i++){
> if(a[i]==a[i+1]){
> next
> }
> }
> }
> n'
a
abc
def
one pair
그 기능은 각 행을 $0
배열로 분할한 a
다음 배열을 정렬하고 n
배열의 길이를 반환하는 것입니다. 그런 다음 배열을 반복하고 정렬된 배열에서 인접한 두 문자가 동일하면 다음 단어로 종료됩니다. 단어 전체를 통과하면 (전체) 입력 줄이 인쇄됩니다. 3개 이상의 단어로 구성된 줄은 반복되는 공백으로 인해 항상 인쇄되지 않습니다.
예 - 반복되는 문자가 없는 다섯 글자 단어를 모두 찾습니다.
$ grep '^.....$' /usr/share/dict/words | tr '[A-Z]' '[a-z]' | awk '{split($1,a,"");n=asort(a);for(i=1;i<=n;i++){if(a[i]==a[i+1]){next}}}n' | head -5
abhor
abide
abies
abilo
abler