Bash에서 중복 문자 제거

Bash에서 중복 문자 제거

줄이 있는 경우:

There are seven pencil

다음과 같이 인쇄하고 싶습니다.

Ther a svn pcil

Bash 쉘 명령이란 무엇입니까?

설명: 목표는 두 번 이상 나타나는 모든 문자(첫 번째 문자 제외)를 제거하는 것입니다.

답변1

s/replace-this/with-that/g전역 교체 = 모든 발생을 의미 하는 sed의 고전적인 구문을 기반으로 누군가 which (확장 ) 대신 gwhich를 사용할 수 있습니다 .2ggglobal replacement but after second occurencegnu sed

삭제만 해당되는 예 e:

$ echo $a
there are seven pencil

$ echo $a | sed 's/e//2g'
ther ar svn pncil

모든 중복 문자를 제거하려면 다음과 같은 트릭을 사용할 수 있습니다.

$ sed -f <(printf 's/%s//2g\n' {a..z}) <<<"$a"
ther a svn pcil

불행히도 이것은 작동하지 않습니다.sed 's/[a-z]//2g'

위의 트릭은 <( )파일로 사용할 수 있는 프로세스 대체를 사용합니다.

내 솔루션에서 절차적 대체는 sedoption=read sed 명령을 통해 파일에서 제공되는 스크립트 파일로 처리됩니다.sed-f

답변2

Awk해결 방법(대소문자 구분):

s="There are seven pencil"
printf '%s\n' "$s" | awk -v FS="" '{ 
           for(i=1; i<=NF; i++) 
               if ($i==" " || !a[$i]++) printf "%s", $i; print "" 
       }'
  • -v FS=""- 각 문자가 별도의 필드가 되도록 "빈" 필드 구분 기호를 설정합니다(POSIX가 아니라 많은 구현에서 지원되는 GNU 확장).
  • for(i=1; i<=NF; i++)- 문자 반복
  • if ($i==" " || !a[$i]++)- 공백 문자이거나 처음 등장하는 문자인 경우

산출:

Ther a svn pcil

대소문자를 구분하지 않으려면 a[$i]로 바꾸십시오 a[tolower($i)].

답변3

이것은 Bash 그 자체입니다.

s="There are seven pencil"
declare -A A
while IFS= read -rn1 a; do
 [ -z "$a" ] || [ -n "${A[$a]}" ] && continue
 printf %s "$a"
 [ "$a" == " " ] || A[$a]=x
done <<<"$s"
echo

한 줄씩 설명:

  1. 변수에 문자열 할당

    s="There are seven pencil"
    
  2. 연관 배열 선언A

    declare -A A
    
  3. 이것은 약간 복잡합니다. 하지만 자세한 내용이 없으면 개별 문자별로 문자열을 읽고 방금 읽은 문자를 에 할당합니다 a. 이것은 while주기입니다.

    while IFS= read -rn1 a; do
    
  4. 현재 문자가 비어 있는 경우( [ -z "$a" ]) 또는 ( ||) 이 키(이 문자)와 관련된 값이 설정된 경우(설정된 경우 여기에 표시됨) 루프를 계속합니다(다음 반복으로 이동하므로 다음 내용을 읽으십시오). 문자)를 다시 인쇄하지 않고 계속 진행합니다).

    [ -z "$a" ] || [ -n "${A[$a]}" ] && continue
    
  5. 현재 문자를 인쇄합니다.

    printf %s "$a"
    
  6. 문자가 공백이면 실행되지 않습니다. A[$a]=x이것이 ||여기서 의미하는 바입니다. A[$a]=x관련된 작업입니다. 모든 공백을 방지하려면 배열의 키 공간에 어떤 값도 할당하면 안 됩니다 A. (4번 항목 참조)

    [ "$a" == " " ] || A[$a]=x
    
  7. 이로써 while사이클이 종료됩니다. <<<"$s"여기에 문자열 리디렉션이 있습니다. 루프를 문자열로 채웁니다.

    done <<<"$s"
    
  8. 마지막으로 echo줄 구분 기호를 인쇄합니다. printf5번 항목에서는 문자만 인쇄됩니다. 이것이 없으면 echo출력은 다음 쉘 프롬프트와 같은 줄에 나타납니다. 그것을 벗고 직접 확인하십시오.

    echo
    

답변4

또 다른 sed해결책:

  • 단일 알파벳 문자의 경우:

    $ echo 'here hear' | sed 's/\(\([[:alpha:]]\).*\)\2/\1'
    here ear
    
  • 이들 모두에 대해 g이미 처리된 문자는 다시 확인되지 않으므로 이 플래그는 도움이 되지 않습니다. 따라서 루프를 사용하면 "t"는 교체가 성공하는 한 레이블로 분기됩니다.

    $ echo There are seven pencils | sed -e :a -e 's/\(\([[:alpha:]]\).*\)\2/\1/; ta'
    Ther a svn pcil
    

    GNU를 사용하면 sed다음과 같이 단축할 수 있습니다.

    sed -E ':a;s/(([[:alpha:]]).*)\2/\1;ta'
    

대소문자 무시(여전히 GNU 사용 sed):

$ echo 'There this That' | sed -E ':a; s/(([[:alpha:]]).*)\2/\1/i; ta'
Ther is a


그 중 perl(ASCII 문자는 여기서만):

$ echo 'There are seven pencil' | perl -pe 'while(s/([a-zA-Z]).*?\K\1//g){}'
Ther a svn pcil
$ echo 'There this That' | perl -pe 'while(s/([a-z]).*?\K\1//gi){}'
Ther is a

관련 정보