sed 음역의 이스케이프 문자

sed 음역의 이스케이프 문자

sed음역( y///)을 사용하여 한 문자 집합을 다른 문자 집합으로 바꾸고 싶습니다 .

이 프로그램을 사용하는 것뿐만 아니라 이것이 효과가 있기를 바랍니다 tr.

$ echo '[]{}abc' | tr '[ab}' 'gefh' 
g]{hefc

그러나 sed를 사용하여 동일한 작업을 수행하면 다음 오류가 표시됩니다.

$ echo '[]{}abc' | sed 'y/[ab}/gefh/' 
sed: 1: "y/[ab}/gefh/": unbalanced brackets ([])

[문자를 이스케이프 처리해야 한다고 예상했기 때문에 이는 의미가 있습니다 . 그러나 이 상황을 벗어나려고 하면 다음과 같은 다양한 오류가 발생합니다.

$ echo '[]{}abc' | sed 'y/\[ab}/gefh/' 
sed: 1: "y/\[ab}/gefh/": transform strings are not the same length

현재 해결 방법은 (1) 그냥 사용 tr하거나 (2) 이스케이프된 문자와 일치하는 것 외에는 아무것도 하지 않는 음역 오른쪽에 "더미 문자"를 삽입하는 것입니다.

$ echo '[]{}abc' | sed 'y/\[ab}/_gefh/' 
g]{hefc

그러나 이는 불만족스럽고 의심스럽습니다. 예를 들어 \입력 문자열 내부에 있는 경우에도 매우 안전하지 않습니다 .

$ echo '[]{}abc\' | sed 'y/\[ab}/_gefh/' 
g]{hefc_

이스케이프 문자 자체를 번역의 일부로 고려하지 않고 sed 음역에서 문자를 이스케이프하는 올바른 방법은 무엇입니까?

답변1

sedmacOS를 사용한다고 가정합니다(macOS용 FreeBSD가 어디에서 왔는지는 확인하지 않았지만 이 문제를 기본적으로 표시할 수 있는 유일한 시스템입니다 sed).

$ echo '[]{}abc' | sed 'y/[ab}/gefh/'
sed: 1: "y/[ab}/gefh/": unbalanced brackets ([])
$ echo '[]{}abc' | sed 'y/\[ab}/gefh/'
sed: 1: "y/\[ab}/gefh/": transform strings are not the same length
$ echo '[]{}abc' | sed 'y/\[ab}/\gefh/'
g]{hefc

그래서,하나해결책은

  1. [불균형한 괄호를 피하기 위해 첫 번째 문자열을 이스케이프 처리 하고
  2. 두 번째 문자열에 "no-op" 백슬래시를 추가하여 두 문자열의 길이를 동일하게 만듭니다.

또는,

  • 두 문자열을 모두 로 감쌀 수도 있습니다 [...]. 이는 문자열의 어디에 있는지 신경 쓰지 않고 기계적으로 수행할 수 있기 때문에 이를 처리하는 가장 안전한 방법일 것입니다 [.

    $ echo '[]{}abc' | sed 'y/[[ab}]/[gefh]/'
    g]{hefc
    
  • sed아니면 macOS에 Homebrew나 FreeBSD의 패키지 시스템을 통해 GNU를 설치해서 사용하세요.

sed나는 이것을 이 구현의 버그라고 생각합니다 .

답변2

당신이 하고 있는 일은 올바른 방법입니다. [sed 에서는 항상 일반 문자여야 합니다 y///. 이는 다음과 같은 문자 클래스의 tr일부가 되는 것과는 다릅니다 .[[:alpha:]

불행하게도 sed의 여러 구현에는 sed에서 균형 잡힌 괄호를 구문 분석하려고 시도하게 만드는 버그가 있는 것 같습니다. 나는 FreeBSD 11.2와 BusyBox 1.30.1에서 당신이 설명하는 버그를 관찰했습니다.

백슬래시 작업은 까다롭습니다. 백슬래시+문자의 동작은 그렇지 않습니다.기준문자가 \, n또는 구분 기호가 아닌 경우. 따라서 특정 구현에서 버그를 해결하는 데 이를 사용할 수 있지만 생성된 코드는 다른 구현에서는 작동하지 않을 수 있습니다.

이식 가능한 해결 방법은 [변경하고 싶지 않은 다른 문자로 일시적으로 바꾸고 동일한 대체에서 자체적으로 변환하는 것입니다 ]. 잘못된 구문 분석을 방지하려면 이 문자가 ], ^또는 이 아니어야 합니다 :. 교환을 수행할 때 대괄호와 그 사이에 있는 내용을 사용하여 문자열을 구성해야 합니다. FreeBSD는 대체를 좋아하지 않습니다 []. 이를 해결하는 간단한 방법은 앞에 추가 문자를 추가하는 것입니다 ]. 예를 들어 B임시 [.

y/[B_]/B[_]/; y/Bab}/gefh/; y/[B_]/B[_]/

관련 정보