[string] sed replace 패턴을위한 문자열을 이스케이프

내 bash 스크립트에는 sed 패턴으로 사용해야하는 외부 (사용자로부터받은) 문자열이 있습니다.

REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"

$REPLACE문자열을 이스케이프 처리하여 sed문자 그대로 대체 할 수 있습니까?

참고 : (가) KEYWORD없는 경기 등 그것은 사용자가 제공되지와 바보 같은 문자열입니다.



답변

경고 : 이것은 개행을 고려 하지 않습니다 . 더 자세한 답변은 이 SO 질문을 참조하십시오 . (감사합니다, Ed Morton & Niklas Peter)

모든 것을 탈출하는 것은 나쁜 생각입니다. Sed는 특별한 의미 를 얻기 위해 많은 캐릭터를 탈출해야 합니다. 예를 들어, 대체 문자열에서 숫자를 이스케이프하면 역 참조로 바뀝니다.

Ben Blank가 말했듯이 대체 문자열에서 이스케이프해야 할 문자는 세 개뿐입니다 (이스케이프, 명령문 끝 및 슬래시 모두 슬래시).

ESCAPED_REPLACE=$(printf '%s\n' "$REPLACE" | sed -e 's/[\/&]/\\&/g')
# Now you can use ESCAPED_REPLACE in the original sed statement
sed "s/KEYWORD/$ESCAPED_REPLACE/g"

KEYWORD문자열 을 이스케이프해야하는 경우 다음이 필요합니다.

sed -e 's/[]\/$*.^[]/\\&/g'

그리고 다음에 의해 사용될 수 있습니다 :

KEYWORD="The Keyword You Need";
ESCAPED_KEYWORD=$(printf '%s\n' "$KEYWORD" | sed -e 's/[]\/$*.^[]/\\&/g');

# Now you can use it inside the original sed statement to replace text
sed "s/$ESCAPED_KEYWORD/$ESCAPED_REPLACE/g"

/분리 문자 이외의 문자를 사용하는 경우 사용중인 문자 와 함께 위의 표현식에서 슬래시를 바꿔야합니다. 설명은 PeterJCLaw의 의견을 참조하십시오.

편집 : 이전에 설명되지 않은 일부 경우로 인해 위의 명령이 여러 번 변경되었습니다. 자세한 내용은 편집 기록을 확인하십시오.


답변

sed 명령을 사용하면 /구분 기호 대신 다른 문자를 사용할 수 있습니다 .

sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'

큰 따옴표는 문제가되지 않습니다.


답변

replace 절에서 특별히 처리되는 세 가지 리터럴 문자는 /( 구문 닫기), \(이스케이프 문자, 역 참조 등) 및 &(대체에 일치 항목 포함)입니다. 따라서이 세 문자를 피하기 만하면됩니다.

sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g')/g"

예:

$ export REPLACE="'\"|\\/><&!"
$ echo fooKEYWORDbar | sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g')/g"
foo'"|\/><&!bar


답변

피아노 사우루스의 정규 표현식을 기반으로 키워드와 대체를 모두 피하는 bash 함수를 만들었습니다.

function sedeasy {
  sed -i "s/$(echo $1 | sed -e 's/\([[\/.*]\|\]\)/\\&/g')/$(echo $2 | sed -e 's/[\/&]/\\&/g')/g" $3
}

사용 방법은 다음과 같습니다.

sedeasy "include /etc/nginx/conf.d/*" "include /apps/*/conf/nginx.conf" /etc/nginx/nginx.conf


답변

응답하는 데 약간 늦었지만 …이 작업을 수행하는 훨씬 간단한 방법이 있습니다. 구분 기호 (예 : 필드를 구분하는 문자) 만 변경하십시오. 따라서 대신에을 s/foo/bar/쓰십시오 s|bar|foo.

이 작업을 수행하는 가장 쉬운 방법은 다음과 같습니다.

sed 's|/\*!50017 DEFINER=`snafu`@`localhost`\*/||g'

결과 출력에는 불쾌한 DEFINER 절이 없습니다.


답변

당신이 잘못된 질문을하고있는 것으로 나타났습니다. 나는 또한 잘못된 질문을했다. 그것이 틀린 이유는 첫 문장의 시작입니다 : “내 bash 스크립트에서 …”.

나는 같은 질문을했고 같은 실수를했다. bash를 사용하는 경우 sed를 사용하여 문자열을 교체 할 필요가 없습니다 ( bash에 내장 된 replace 기능을 사용하는 것이 훨씬 깨끗합니다).

예를 들어,

function escape-all-funny-characters() { UNKNOWN_CODE_THAT_ANSWERS_THE_QUESTION_YOU_ASKED; }
INPUT='some long string with KEYWORD that need replacing KEYWORD.'
A="$(escape-all-funny-characters 'KEYWORD')"
B="$(escape-all-funny-characters '<funny characters here>')"
OUTPUT="$(sed "s/$A/$B/g" <<<"$INPUT")"

배쉬 기능을 독점적으로 사용할 수 있습니다 :

INPUT='some long string with KEYWORD that need replacing KEYWORD.'
A='KEYWORD'
B='<funny characters here>'
OUTPUT="${INPUT//"$A"/"$B"}"


답변

awk를 사용하십시오-더 깨끗합니다 :

$ awk -v R='//addr:\\file' '{ sub("THIS", R, $0); print $0 }' <<< "http://file:\_THIS_/path/to/a/file\\is\\\a\\ nightmare"
http://file:\_//addr:\file_/path/to/a/file\\is\\\a\\ nightmare