sed를 사용하여 문자 간격 실행 취소

sed를 사용하여 문자 간격 실행 취소

이 질문의 단어가 "문자 간격"인 것처럼 일부 단어가 문자 간격으로 배치된 일부 텍스트가 포함된 소스 텍스트 파일이 있습니다(즉, 단어 문자 사이에 공백 문자가 있습니다.

sed를 사용하여 문자 간격을 제거하는 방법은 무엇입니까?

이와 같은 패턴은 \{[A-Za-z] \}+[A-Za-z]문자 간격 단어를 캡처하고 s/ //g공백을 제거합니다. 그러나 텍스트 줄에서 문자 간격 단어를 추출하고 나머지 텍스트의 올바른 공백 문자를 손상시키지 않고 문자 간격을 취소하려면 어떻게 해야 합니까?

답변1

다음을 수행할 수 있습니다.

sed     -e's/ \([^ ][^ ]\)/\n\1/g' \
        -e's/\([^ ][^ ]\) /\1\n/g' \
        -e's/ //g;y/\n/ /
'       <<\IN
I have a source text file containing text where
some words are l e t t e r s p a c e d
like the word "letterspaced" in this question
(i.e., there is a space character between the
letters of the word. 
IN

아이디어는 먼저 두 개 이상의 공백이 아닌 문자가 앞이나 뒤에 오는 모든 공백을 찾아서 개행 문자로 따로 설정하는 것입니다. 다음으로 남은 공백을 모두 제거하세요. 마지막으로 모든 개행 문자를 다시 공백으로 변환합니다.

완벽하지는 않습니다. 모든 단어가 포함된 완전한 사전이 없으면 일종의 경험적 방법을 사용하는 것이 가장 좋습니다. 근데 이거 좀 괜찮은데

또한 사용 중인 항목에 따라 sed리터럴 개행 문자를 대신 사용해야 할 수도 있습니다.n나는 처음 두 개의 바꾸기 문에도 사용하고 있습니다.

그러나 이 주의사항 외에 이는 모든 POSIX에서 작동하며 매우 빠르게 작동합니다 sed. 불가능한 경우를 저장하기 때문에 비용이 많이 드는 정방향 또는 역방향 작업을 수행할 필요가 없습니다. 이는 단일 주소의 모든 대체에 대한 모든 패턴 공간을 처리할 수 있음을 의미합니다.

산출

I have a source text file containing text where some
words are letterspaced
like the word "letterspaced" in this question
(i.e., there is a space character between the
letters of the word.

답변2

가장 효율적인 Perl 방법:

perl -C -lpe 's/(?:^|\P{L})\K\p{L}(?:\s\p{L})+(?=\P{L}|$)/$&=~s{\s}{}rgo/goe'

/r이는 귀하의 Perl 버전이 대체되는 플래그를 이해할 만큼 충분히 새로운 버전이라고 가정합니다 .

개념의 증거:

$ echo  'Do I like «ł é t t ê r s p ä c è đ» text?' | perl -C -lpe 's/(?:^|\P{L})\K\p{L}(?:\s\p{L})+(?=\P{L}|$)/$&=~s{\s}{}rgo/goe'
Do I like «łéttêrspäcèđ» text?

답변3

Perl의 예측 단언을 사용하면 이를 쉽게 수행할 수 있습니다. AFAIK, sed에는 이것이 부족합니다.

두 개 이상의 공백이 단어를 구분하는 경우 단일 공백은 제거되지만 두 개 이상의 시퀀스는 변경되지 않습니다.

perl -pe 's/\s(?!\s)//g' myfile

p스위치를 사용하면 Perl은 뒤에 다른 공백이 오지 않는 단일 공백( )을 읽고 myfile교체 합니다. \s이것은 주어진 부정적인 예측 주장입니다 (?!\s).

관련 정보