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
-c
sed 1s_
_o_ <(echo $1)
h
./file with space
sed 1s_
sed
1s_
작은 따옴표로 묶인 문자열 안에 작은 따옴표로 묶인 문자열을 넣으려고 하지만 이는 불가능합니다. 두 번째 작은 따옴표가 작은 따옴표로 묶인 문자열을 끝냅니다. '\''
리터럴을 작은따옴표로 끝낸 다음 리터럴을 작은따옴표로 묶고 리터럴을 다시 작은따옴표로 시작할 수 있습니다 .
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)'
전달됩니다 .bash
sed
명령을 수정하려면 매개변수에 큰따옴표를 사용해야 합니다 sed
.
$ find . -maxdepth 1 -name "* *" -exec bash -c 'sed "1s_ _o_" <(echo $1)' h {} \;