`sed`를 사용하여`tr`과 같은 문자를 번역 할 수 있습니까?


14

일련의 문자를 다른 세트의 해당 문자로 바꾸고 싶습니다.

original set: ots
"target" set: u.x

foobartest → fuubar.ex.

이와 같은 번역 / 음역은이 tr명령 의 전문 분야입니다 .

$ echo 'foobartest' | tr 'ots' 'u.x'
fuubar.ex.

불행히도 tr파일을 변경하는 것은 지원하지 않습니다 sed. 임시 파일을 저글링하는 바퀴를 다시 만들 필요가 없도록
사용 sed하고 싶습니다.


"sed translate characters"에 대한 결과를 찾지 못한 것이므로이 질문에 스스로 답하십시오. 마법의 키워드는 결국 "음역"이되었지만이 기능을 최대한 쉽게 찾을 수있는 가치가 있다고 생각했습니다.
n.st

이에 대한 해결 방법을 구현할 때 명심해야 할 사항 : tr(정확하게) 대체 세트의 재귀를 무시합니다. echo 'abc' | tr ab bxbxc. 원시 솔루션은 xxc번역을 이미 번역 된 문자에 다시 적용 하기 때문에이를 정체시킬 수 있습니다 .
n.st

관련 : TR 아날로그 유니 코드 문자를? (GNU sed와는 반대로 tr멀티 바이트 문자를 음역 할 수 있음)
Stéphane Chazelas

다른 가능성을 원한다면 : perl은 번역하고 -i와 (고대가 아닌 경우) 멀티 바이트를 수행 할 수 있습니다. POSIX는 아니지만 꽤 일반적입니다.
dave_thompson_085

답변:


24

sed다음 y과 같이 작동 하는 명령이 있습니다 tr.

$ echo 'foobartest' | sed 'y/ots/u.x/'
fuubar.ex.

y명령은 POSIX sed사양의 일부 이므로 거의 모든 플랫폼에서 작동해야합니다.

그리고이므로 sed파일을 편집 된 버전으로 바꾸어 귀찮은 임시 파일 사업을 피할 수 있습니다 ( POSIX에서 지정하지 않은 옵션 sed지원 -i옵션을 제공 한 경우).

$ sed -i 'y/ots/u.x/' some-file.txt

@ StéphaneChazelas 지적 해 주셔서 감사합니다. 나는 지금까지 내면의 일을 알지 못했습니다. 나는 그것을 언급하기 위해 대답을 편집했습니다.
n.st

고마워, 이것은 매우 유용합니다! VIM (CentOS 7.3의 8.0.1092)에서 작동 할 것으로 예상했지만 작동하지 않습니다. sed는하지 말아야합니까, VIM은합니까?
dotancohen

1
@dotancohen Vim의 대체 함수가 sed's'를 따라 모델링 되었다고 해서 다른 함수도 마찬가지라는 의미는 아닙니다. ;) Vim 메일 링리스트에는 동등한 것을 찾는 스레드 가 있습니다 y/abc/def/. 가장 좋은 옵션은 :%call setline(".", tr(getline("."),"abc","def"))입니다.
n.st

8

귀하의 경우와 마찬가지로 크기를 변경하지 않고 문자를 음역하고 있습니다 (어쨌든 GNU와 같은 일부 구현은 tr단일 바이트 문자 만 지원합니다).

tr 'ots' 'u.x' < file 1<> file

즉, tr파일 자체를 덮어 씁니다.

sed -i여러 계정 보다 낫습니다 .

  • 추가 디스크 공간이 필요하지 않습니다 (일부 스파 스 파일, 기록 중 복사 특수 경우 제외)
  • 그것은 inode 번호, 소유권, 권한, ACL을 유지합니다 ...
  • 심볼릭 링크로 작동하지만 하드 링크를 끊지 않습니다.
  • 죽일 때 임시 파일을 남기지 않습니다.

한 가지 단점은 파일이 중단되면 파일이 반으로 번역된다는 것입니다 (이 경우 파일을 다시 실행하여 완료 할 수 있음). 일부 sed구현은 명령이 성공하지 않는 한 원본 파일을 변경하지 않고 유지함으로써이를 올바르게 처리합니다.


3
번역 세트에 재귀가있는 경우 번역을주의해서 다시 실행하십시오 (예 :) echo 'abc' | tr ab bx.
n.st

1
@ n.st, 그렇습니다. 그래서이 경우에는 철자를 쓰는 것이 가치가 있다고 동의하지만 말한 것입니다.
Stéphane Chazelas

결국, 나는 임시 파일로 작업해야했다. gist.github.com/n-st/048facd0c12f105ac122030fb58b962f — 멀티 바이트 문자로 인해 GNU를 사용할 수 없었고tr symlink가 많은 PXE 환경에서 sed -i스크류 업 대기 일어날 일이… : /
n.st.

@ n.st, iconv -t cp437더 적합 해 보입니다.
Stéphane Chazelas

iconv입력 파일에 이미 cp437로 인코딩 된 바이트가 포함되어 있거나 여러 인코딩이 혼합 된 경우 중단됩니다. 따라서 일반적인 경우에 바람직하지만이 경우 수동 교체를 수행하는 것이 더 강력합니다.
n.st

4

다른 대안으로, 주요 문제가 파일을 변경하는 지원이 부족한 sponge경우 moreutils 패키지 의 도구에 관심이있을 수 있습니다 .

tr 'ots' 'u.x' < file | sponge file

file에 쓰지만 file입력이 완료된 후에 만 쓰기 위해 열립니다 . 로부터 :

sponge표준 입력을 읽고 지정된 파일에 씁니다. 쉘 리디렉션과 달리 스폰지는 출력 파일을 열기 전에 모든 입력을 흡수합니다. 이를 통해 동일한 파일에서 읽고 쓰는 파이프 라인을 구성 할 수 있습니다.

실제로 메모리에 보관할 수없는 대용량 파일이 없으면 sponge효과가 있습니다.


2
한 가지 문제는 sponge여전히 덮어 쓰는 것입니다 file경우 tr(당신이 쓰기가 있다면 예를 들어 있지만 액세스를 읽을 실패 file)
스테판 Chazelas가

아, 실제로 그렇습니다. 나는 그것을 기대하지 않았다. 감사.
mindriot

cat file >; file명령이 성공한 경우에만 대상으로 이름이 바뀐 임시 파일에 출력을 기록하는 ksh93 연산자를 참조하십시오 (그러나 sed -i원본을 겹쳐 쓰지 않고 새 파일을 작성 함).
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.