"find ... -exec" 내에서 "sed"의 백슬래시를 이스케이프 처리하는 방법은 무엇입니까?

"find ... -exec" 내에서 "sed"의 백슬래시를 이스케이프 처리하는 방법은 무엇입니까?

다른 하위 디렉터리에 있는 일부 파일의 줄을 변경하고 싶습니다. 파일의 확장자는 항상 .dct이며 작업 디렉터리의 다른 하위 디렉터리에 있는 하위 디렉터리에 항상 존재합니다 mod(그러나 하위 디렉터리가 많아서 를 mod사용합니다 find). 하지만 내가 바꾸고 싶은 문자열은 디렉터리(Windows -> Unix)입니다.

를 통해 관련 파일을 얻을 수 있습니다 find . -type f -path '*/mod/*.dct. 으로 관련 줄을 변경해 보았습니다 sed -e 's/cd c:\\project\\data\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod.

나는 범인이 되는 탈출된 백슬래시로 범위를 좁혔습니다. 이것은 작동합니다:

find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c://' $(basename {}) > $(basename {}).mod"

다음은 수행되지 않습니다.

find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"

이건 오류야

sed: -e expression #1, char 7: unterminated `s' command

char 7부분은 탈출에 문제가 있다는 생각이 들게 합니다. 그런 것 같은데 어떻게 고칠 수 있는지 모르겠습니다. 이를 설명하기 위해 다음이 작동합니다.

find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"

따라서 " 무엇이든 대체" sed -e 's/c:\\///'로 이스케이프되고 "무엇으로 대체" 대신 "...로 대체 "(그리고 오류 발생)로 이스케이프된 것처럼 보입니다 .c:\/sed -e 's/c:\\//'c:\/c:\

참고: 대신 -execdir에 and를 사용하는 것은 약간 과잉일 수 있지만 어딘가에서 이것이 좋은 형식이라는 것을 읽었습니다.basename-exec

답변1

질문의 핵심은 from을 호출하여 백슬래시(예: \)를 슬래시(예: )로 바꾸는 방법입니다 . /이렇게 하려면 문자열이 호출에 의해 한 번, 호출에 의해 두 번, 두 번 처리되기 때문에 백슬래시를 두 번 이스케이프 처리해야 합니다. 그러면 다음 정보가 제공됩니다.sedfindfindsed

find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/cd c:\\\\project\\\\data\\\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod" \;

아래는 좀 더 자세한 설명입니다.


먼저 문제에 대한 약간 더 간단한 예를 설정해 보겠습니다.

# Create a target directory
mkdir -p /tmp/dir1/mod/dir2

# Create a text file containing a backslash
echo '\' > /tmp/dir1/mod/dir2/file.dct

이제 백슬래시를 사용 find하고 sed이를 슬래시로 바꿔 보겠습니다.

find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\/\//' $(basename {})" \;

이로 인해 다음 오류가 발생합니다.

sed: -e expression #1, char 7: unterminated `s' command

sed이는 실행되는 명령이 다음과 같기 때문입니다 .

sed -e 's/\/\//' ./file.dct

다음 명령을 직접 실행하여 동일한 오류가 발생하는지 확인할 수 있습니다. 예:

sed -e 's/\/\//' /tmp/dir1/mod/dir2/file.dct

다음과 같은 명령을 실행하여 이를 확인할 수도 있습니다 echo.find

find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir echo "sed -e 's/\\/\//' $(basename {})" \;

명령을 수정하려면 백슬래시를 두 번 이스케이프 처리합니다.

find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\\\/\//' $(basename {})" \;

그러면 원하는 결과가 생성됩니다.

/

관련 정보