문자열을 검색하고 sed 명령을 통해 바꾸는 스크립트가 있습니다. 문자열에 특수 문자가 포함되어 있으면 스크립트는 특수 문자를 이스케이프 처리합니다(슬래시는 제외됩니다. 슬래시는 현재 sed 구분 기호이고 열은 bash 행의 문자열을 표시하기 때문입니다).
문제는 다음과 같습니다.
raw_searchstring='SearchForThis';
raw_replacementstring='ReplaceWithThis';
#Escape special characters:
quoted_searchstring=$(printf %s "$raw_searchstring" | sed 's/[][()\.^$?*+]/\\&/g');
quoted_replacementstring=$(printf %s "$raw_replacementstring" | sed 's/[][()\.^$?*+]/\\&/g');
find ./ -type f -exec sed -i -r "s/$quoted_searchstring/$quoted_replacementstring/" {} \;
우분투에서 이것을 테스트했는데 훌륭하게 작동합니다.
그러나 AIX 시스템에서는 스크립트를 실행해야 합니다. sed -i를 사용한 인라인 편집을 지원하지 않기 때문에 여기 비슷한 질문에서 제안한 대로 다음을 시도했습니다(AIX용 sed - 내부 편집):
find ./ -type f -exec sed -r 's/$quoted_searchstring/$quoted_replacementstring/' infile > tmp.$$ && mv tmp.$$ infile {} \;
여기서 오류가 발생합니다.
find: missing argument to `-exec'
find
그래서 다음 줄을 사용하여 여러 -exec 문을 전달해 보았습니다.
find /home/tobias/Desktop -type f -exec sed -r 's/$quoted_searchstring/$quoted_replacementstring/' infile > tmp.$$ {} \; -exec mv tmp.$$ infile {} \;
이것도 작동하지 않습니다.
sed: can't read infile: No such file or directory
내가 뭘 잘못하고 있는지 잘 모르겠습니다. 이 코드 줄을 수정하거나 올바른 방향을 알려줄 수 있나요?
답변1
실행된 명령에서 및 같은 셸 연산자를 사용하려고 했기 때문에 시도가 작동하지 않지만 &&
이러한 연산자를 명령에 직접 입력하여 호출 셸에서 실행합니다. 귀하의 명령은 다음과 같이 구문 분석됩니다.>
find
find
find … > tmp.$$ && mv …
예를 들어 첫 번째 find
호출은 다음과 같습니다.
find ./ -type f -exec sed 's/$quoted_searchstring/$quoted_replacementstring/' infile
출력은 으로 리디렉션됩니다 tmp.$$
. 이 명령에는 다른 문제가 있습니다. ( infile
이것은 {}
발견된 파일입니다. find
) sed 표현식 주위의 작은따옴표는 쉘 변수를 사용하고 있기 때문에 큰따옴표여야 합니다.
실행된 명령에 쉘 구성을 사용해야 하므로 실행 쉘에 find
알려주세요 .find
find … -exec sh -c '…' {} \;
인용 문제를 피하려면 인용해야 하는 항목(예: sed 표현식)을 인수로 에 전달하세요 sh
.
find ./ -type f -exec sh -c '
sed "$0" "$1" >"$1.new" && mv "$1.new" "$1"
' "s/$quoted_searchstring/$quoted_replacementstring/" {} \;
약간의 가독성 손실로 약간의 성능 향상을 위해 양식 -exec … {} +
과 셸 루프를 사용할 수 있습니다.
find ./ -type f -exec sh -c '
for x; do
sed "$0" "$x" >"$x.new" && mv "$x.new" "$x";
done
' "s/$quoted_searchstring/$quoted_replacementstring/" {} +
또는 AIX 버전이 ksh93
너무 오래되지 않은 경우 재귀 와일드카드 기능(ksh93p에 도입됨)을 사용할 수 있습니다.
set -G
for x in **; do
[[ -f $x ]] || continue
sed "s/$quoted_searchstring/$quoted_replacementstring/" "$x" >"$x.new" && mv "$x.new" "$x";
done
-r
어쨌든 ERE 사용을 위한 플래그는 GNU 확장이므로 기본 정규식을 생성하려면 문자열-정규식 변환도 조정해야 합니다 . 또한 기존 코드에는 몇 가지 버그가 있습니다. 슬래시를 인용하는 것을 잊었고 대체 텍스트에서 올바른 문자를 인용하지 않았습니다.
quoted_searchstring=$(printf %s "$raw_searchstring" | sed 's![[\/.^$*]!\\&!g');
quoted_replacementstring=$(printf %s "$raw_replacementstring" | sed -e 's![][\/&]!\\&!g' -e '!$ s!$!\\!');