줄이 있는 경우:
There are seven pencil
다음과 같이 인쇄하고 싶습니다.
Ther a svn pcil
Bash 쉘 명령이란 무엇입니까?
설명: 목표는 두 번 이상 나타나는 모든 문자(첫 번째 문자 제외)를 제거하는 것입니다.
답변1
s/replace-this/with-that/g
전역 교체 = 모든 발생을 의미 하는 sed의 고전적인 구문을 기반으로 누군가 which (확장 ) 대신 g
which를 사용할 수 있습니다 .2g
g
global replacement but after second occurence
gnu 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'
위의 트릭은 <( )
파일로 사용할 수 있는 프로세스 대체를 사용합니다.
내 솔루션에서 절차적 대체는 sed
option=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
한 줄씩 설명:
변수에 문자열 할당
s="There are seven pencil"
연관 배열 선언
A
declare -A A
이것은 약간 복잡합니다. 하지만 자세한 내용이 없으면 개별 문자별로 문자열을 읽고 방금 읽은 문자를 에 할당합니다
a
. 이것은while
주기입니다.while IFS= read -rn1 a; do
현재 문자가 비어 있는 경우(
[ -z "$a" ]
) 또는 (||
) 이 키(이 문자)와 관련된 값이 설정된 경우(설정된 경우 여기에 표시됨) 루프를 계속합니다(다음 반복으로 이동하므로 다음 내용을 읽으십시오). 문자)를 다시 인쇄하지 않고 계속 진행합니다).[ -z "$a" ] || [ -n "${A[$a]}" ] && continue
현재 문자를 인쇄합니다.
printf %s "$a"
문자가 공백이면 실행되지 않습니다.
A[$a]=x
이것이||
여기서 의미하는 바입니다.A[$a]=x
관련된 작업입니다. 모든 공백을 방지하려면 배열의 키 공간에 어떤 값도 할당하면 안 됩니다A
. (4번 항목 참조)[ "$a" == " " ] || A[$a]=x
이로써
while
사이클이 종료됩니다.<<<"$s"
여기에 문자열 리디렉션이 있습니다. 루프를 문자열로 채웁니다.done <<<"$s"
마지막으로
echo
줄 구분 기호를 인쇄합니다.printf
5번 항목에서는 문자만 인쇄됩니다. 이것이 없으면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