SED 교체 패턴을 위해 문자열을 피하십시오
문제
내 배쉬 스크립트에는 외부 (사용자로부터 수신) 문자열이 있으며 SED 패턴으로 사용해야합니다.
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
어떻게 탈출 할 수 있습니까? $REPLACE
문자열은 안전하게 받아 들여질 수 있습니다 sed
문자 그대로 교체?
노트: 그만큼 KEYWORD
일치 등이없는 멍청한 서브 스트링입니다. 사용자가 제공하지 않습니다.
해결책
경고: 이건 그렇습니다 ~ 아니다 Newlines를 고려하십시오. 더 심층적 인 대답은 참조하십시오 이 소위 대신에. (감사합니다, Ed Morton & Niklas Peter)
모든 것을 피하는 것은 나쁜 생각입니다. SED는 탈출해야 할 많은 캐릭터가 필요합니다 가져 오기 그들의 특별한 의미. 예를 들어, 교체 문자열에서 숫자를 탈출하면 역전으로 전환됩니다.
Ben Blank가 말했듯이, 교체 문자열에서 탈출 해야하는 3 개의 문자 만 있습니다 (자신의 탈출, 성명서의 끝을위한 슬래시 및 모두 교체) :
sed -e 's/[\/&]/\\&/g'
당신이 탈출해야한다면 KEYWORD
문자열, 다음은 필요한 것입니다.
sed -e 's/[]\/$*.^[]/\\&/g'
다른 캐릭터를 사용하는 경우 기억하십시오 /
Delimiter로서 사용중인 문자 위의 표현식에서 슬래시를 교체해야합니다. 설명은 Peterjclaw의 의견을 참조하십시오.
편집 : 이전에 설명되지 않은 일부 코너 케이스로 인해 위의 명령은 여러 번 변경되었습니다. 자세한 내용은 편집 기록을 확인하십시오.
다른 팁
SED 명령을 사용하면 대신 다른 문자를 사용할 수 있습니다. /
분리기 :
sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'
이중 인용문은 문제가되지 않습니다.
교체 절에서 특별히 취급되는 유일한 세 문자 문자는 다음과 같습니다. /
(조항을 닫으려면), \
(캐릭터, 역전, & c.를 탈출하려면) &
(교체에 일치를 포함시키기 위해). 따라서, 당신이해야 할 일은이 세 캐릭터를 피하기 만하면됩니다.
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
피아노 사우루스의 정규 표현을 바탕으로 키워드와 교체를 모두 피하는 배쉬 기능을 만들었습니다.
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'
결과 출력에는 그 불쾌한 정의 조항이 없습니다.
당신이 잘못된 질문을하는 것이 밝혀졌습니다. 나는 또한 잘못된 질문을했다. 그것이 잘못된 이유는 첫 번째 문장의 시작입니다. "내에서 세게 때리다 스크립트...".
나는 같은 질문을했고 같은 실수를했다. Bash를 사용하는 경우 Sed를 사용할 필요가 없습니다. 많이 청정기 Bash에 내장 된 교체 기능을 사용하려면).
예를 들어 : 예를 들어 :
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")"
Bash 기능을 독점적으로 사용할 수 있습니다.
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
다음은 내가 얼마 전에 사용한 멍청한 예입니다. 새로운 멍청한 인쇄를 인쇄하는 것은 어색한 것입니다. Awk and Sed 비슷한 것은 좋은 템플릿 일 수 있습니다.
ls | awk '{ print "awk " "'"'"'" " {print $1,$2,$3} " "'"'"'" " " $1 ".old_ext > " $1 ".new_ext" }' > for_the_birds
과도하게 보이지만 어떻게 든 인용문의 조합은 '인쇄 된'리터럴로 인쇄하는 데 작동합니다. 그런 다음 내가 정확하게 기억한다면 Vaiables는 다음과 같은 인용문으로 둘러싸여 있습니다 : "$ 1". 그것을 시도하고 SED와 어떻게 작동하는지 알려주세요.
나는 탭과 같은 특수 문자로 깨질 것입니다.
function sedeasy_improved {
sed -i "s/$(
echo "$1" | sed -e 's/\([[\/.*]\|\]\)/\\&/g'
| sed -e 's:\t:\\t:g'
)/$(
echo "$2" | sed -e 's/[\/&]/\\&/g'
| sed -e 's:\t:\\t:g'
)/g" "$3"
}
그래서, 다른 것은 무엇입니까? $1
그리고 $2
쉘 확장을 피하고 탭 또는 이중 공간을 보존하기 위해 인용구로 싸여 있습니다.
추가 배관 | sed -e 's:\t:\\t:g'
(좋아요 :
탭을 변환하는 토큰) \t
.
"and '주변의 쉘 제한으로 발생하는 모든 즐거움을 잊지 마십시오.
So (KSH)
Var=">New version of \"content' here <"
printf "%s" "${Var}" | sed "s/[&\/\\\\*\\"']/\\&/g' | read -r EscVar
echo "Here is your \"text\" to change" | sed "s/text/${EscVar}/g"
사례가 전달할 임의의 암호를 생성하는 경우 sed
패턴을 교체 한 다음 임의 문자열의 문자 세트에주의를 기울 이도록 선택하십시오. Base64로 값을 인코딩하여 만들어진 비밀번호를 선택하면 Base64에서 가능하고 특수 문자 인 문자 만 있습니다. sed
패턴을 교체하십시오. 해당 문자는 "/"이며 생성하는 비밀번호에서 쉽게 제거됩니다.
# password 32 characters log, minus any copies of the "/" character.
pass=`openssl rand -base64 32 | sed -e 's/\///g'`;
SED 명령에서 변수 값을 바꾸려고하는 경우 예제를 제거하십시오.
sed -i 's/dev-/dev-$ENV/g' test to sed -i s/dev-/dev-$ENV/g test
이 작업을 수행하는 더 쉬운 방법은 단순히 문자열을 손에 구축하고 매개 변수로 사용하는 것입니다. sed
rpstring="s/KEYWORD/$REPLACE/g"
sed -i $rpstring test.txt