`sed` 치환으로 보간 된 문자열이 모든 메타 문자를 이스케이프하도록하는 방법


21

텍스트 스트림을 읽고 나중에 실행되는 sed 명령 파일을 생성하는 스크립트가 sed -f있습니다. 생성 된 sed 명령은 다음과 같습니다.

s/cid:image002\.gif@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1922/g
s/cid:image003\.gif@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1923/g
s/cid:image004\.jpg@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1924/g

sed명령 을 생성하는 스크립트 가 다음과 같다고 가정하십시오 .

while read cid fileid
do
    cidpat="$(echo $cid | sed -e s/\\./\\\\./g)"
    echo 's/'"$cidpat"'/https:\/\/mysite.com\/files\/'"$fileid"'/g' >> sedscr
done

cid문자열의 모든 정규식 메타 문자 가 이스케이프되고 보간 되도록 스크립트를 개선하려면 어떻게해야 합니까?

답변:


24

(여기 에서 각각) s명령 의 왼쪽과 오른쪽에 사용되는 변수를 이스케이프하려면 다음을 수행하십시오.sed$lhs$rhs

escaped_lhs=$(printf '%s\n' "$lhs" | sed 's:[][\/.^$*]:\\&:g')
escaped_rhs=$(printf '%s\n' "$rhs" | sed 's:[\/&]:\\&:g;$!s/$/\\/')

sed "s/$escaped_lhs/$escaped_rhs/"

참고 $lhs개행 문자를 포함 할 수 없습니다.

즉, LHS에서 모든 정규 표현식 연산자 ( ][.^$*), 이스케이프 문자 자체 ( \) 및 구분 기호 ( /)를 이스케이프 처리 하십시오 .

RHS에서는, &구분 기호, 백 슬래시 및 줄 바꿈 문자 만 이스케이프하면됩니다 (마지막 줄을 제외한 각 줄 끝에 백 슬래시를 삽입하여 수행함 $!s/$/\\/).

그것은 당신이 사용하는 가정 /당신의 구분자로 sed s명령 및 사용하지 않는 것이 확장 된 RE-r(GNU는 sed/ ssed/ ast/ busybox sed) 또는 -E(BSD의, ast최근 GNU, 최근 비지 박스) 또는 PCREs-R( ssed) 또는 증강 된 RE-A/ -X( ast)한다 모두 추가 RE 연산자가 있습니다.

임의의 데이터를 처리 할 때 몇 가지 기본 규칙 :

  • 사용하지 마십시오 echo
  • 변수를 인용하십시오
  • 로케일의 영향을 고려하십시오 (특히 문자 세트 : 이스케이프 sed 명령은 이스케이프 된 문자열을 sed사용하는 명령 과 동일한 로케일 (및 동일한 명령 사용) 과 같은 로케일에서 실행되는 것이 중요 합니다)sed
  • 개행 문자를 잊지 마십시오 (여기에서 $lhs포함 여부를 확인 하고 조치를 취할 수 있음).

또 다른 옵션은 환경에서 문자열 perl대신 사용 sed하고 문자열을 전달하고 문자 그대로 문자열을 가져 오기 위해 \Q/ \E perlregexp 연산자를 사용하는 것입니다 .

A="$lhs" B="$rhs" perl -pe 's/\Q$ENV{A}\E/$ENV{B}/g'

perl(기본적으로)는 로케일의 문자 집합에 영향을받지 않으며, 위의 경우 사용자에게 어떤 문자 (있는 경우)를 신경 쓰지 않고 문자열을 바이트 배열로 간주합니다. 를 사용하면 모든 명령에 대해 sed로케일을 C로 고정하여 동일한 결과를 얻을 수 있습니다 (오류 메시지의 언어에도 영향을 미칩니다).LC_ALL=Csed


큰 따옴표를 이스케이프 처리하려면 어떻게해야합니까?
Menon

@Menon, 큰 따옴표는 특별 sed하지 않으므로 이스케이프 처리하지 않아도됩니다.
Stéphane Chazelas

와일드 카드를 사용한 패턴 일치에는 사용할 수 없습니까?
Menon

@Menon는 아니와 같은 와일드 카드 패턴 일치 find들 ' -name정규식 다르다. 거기에서 당신은 탈출 ?, *백 슬래시 및[
스테판 Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.