find의 -exec 옵션에서 sed 대체 명령을 사용할 때 문제가 발생했습니다.

find의 -exec 옵션에서 sed 대체 명령을 사용할 때 문제가 발생했습니다.

1을 입력하세요:

find . -maxdepth 1 -name "* *" -exec bash -c 'sed -n '1p' <(echo $1)' h {} \;

출력 1:

./file with space

2를 입력하세요:

find . -maxdepth 1 -name "* *" -exec bash -c 'sed "1s_ _._" <(echo $1)' h {} \;

출력 2:

./file.with.space

3을 입력하세요:

find . -maxdepth 1 -name "* *" -exec bash -c 'sed '1s_ _o_' <(echo $1)' h {} \;

출력 3:

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

출력 3이 잘못된 이유는 무엇입니까? 이 경우 작은따옴표와 큰따옴표의 차이점은 무엇입니까?

답변1

쉘 구문 분석 후 세 번째 명령은 find, ., -maxdepth, 1, -name, , * *, , -exec, bash, -c, sed 1s_, _o_ <(echo $1), h, 로 {}구성됩니다 ;. sed 1s_다음 인수와 마찬가지로 공백이 작은따옴표 리터럴 안에 있기 때문에 단어는 단일 인수입니다. 따라서 find도착 하면 매개변수 , , , 로 실행 ./file with space됩니다 . 쉘 스크립트는 매개변수가 있는 명령이며 , 이는 올바른 형식의 sed 스크립트가 아닙니다.bash-csed 1s__o_ <(echo $1)h./file with spacesed 1s_sed1s_

작은 따옴표로 묶인 문자열 안에 작은 따옴표로 묶인 문자열을 넣으려고 하지만 이는 불가능합니다. 두 번째 작은 따옴표가 작은 따옴표로 묶인 문자열을 끝냅니다. '\''리터럴을 작은따옴표로 끝낸 다음 리터럴을 작은따옴표로 묶고 리터럴을 다시 작은따옴표로 시작할 수 있습니다 .

find . -maxdepth 1 -name "* *" -exec bash -c 'sed '\''1s_ _o_'\'' <(echo $1)' h {} \;

물론 <(echo $1)단일 공백이 아닌 와일드카드 또는 일련의 공백이 포함된 파일 이름은 손상됩니다. 대신에 왜 이런 글을 썼는지 모르겠습니다 <<<"$1".

답변2

나는 이것이 bash 명령에 대해 작은 따옴표를 닫고 있기 때문이라고 생각합니다.-씨옵션.

bash따라서 , 첫 번째 인수 -c, 두 번째 인수 sed 1s_, 세 번째 인수 _o_ <(echo $1)등을 실행 중입니다 . 이와 같이:

$ bash -c 'sed 1s_' '_o_ <(echo $1)'

세 번째 매개변수( )는 가 아닌 에 '_o_ <(echo $1)'전달됩니다 .bashsed

명령을 수정하려면 매개변수에 큰따옴표를 사용해야 합니다 sed.

$ find . -maxdepth 1 -name "* *" -exec bash -c 'sed "1s_ _o_" <(echo $1)' h {} \;

관련 정보