종료되지 않은 's' 명령

종료되지 않은 's' 명령

다른 유사한 질문을 살펴봤지만 답변이 도움이 되지 않았습니다. 저는 bash를 처음 접했고 스크립트에 구문 오류가 있을 수 있지만 어디에 있는지 모르겠습니다. 이 스크립트를 실행할 때마다 example.conf 파일의 사용자를 업데이트하려고 합니다. 각 사용자에게는 name.pub 파일이 있습니다.

VAR1=$( ls  | grep ".pub" |sed "s/.pub//g")
VAR2="@demo_project_users = "
res=$VAR2$VAR1
sed  "s/@demo_project_users = .*/$res/g" example.conf

이렇게 하면 Unterminated 's' command오류가 발생합니다.

편집: 이 파일들을 폴더에 넣었습니다

aaaaaaaaaa.pub  eboh.pub      get_usernames.sh  mmusterfrau.pub  plom.pub   rrein.pub  update_users.sh
dboh.pub        example.conf  leni.pub          mmustermann.pub  rcall.pub  tani.pub

아래와 같이 사이에 공백을 두고 모든 사용자 이름(.pub 제외)을 한 줄에 입력하고 싶습니다.

@demo_project_users = (... all  names here)

답변1

파일 grep이름은 주어진 값에 $res개행 문자가 포함된 여러 파일 이름과 일치할 수 있습니다. sed리터럴 개행 문자가 포함된 대체 문자열을 사용할 때 GNU는 설명하는 방식으로 불평합니다.

grep필터링된 출력 에는 사용하지 마십시오 ls. 패턴과 일치하는 현재 디렉토리의 모든 이름을 얻으려면 *.pub다음을 사용하십시오.

filenames=( *.pub )

그러면 주어진 패턴과 일치하는 모든 이름을 포함하는 배열이 생성됩니다.

그 다음에:

sed 's/\(@demo_project_users = \).*/\1'"${filenames[*]%.pub}"'/g' example.conf

Expand는 "${filenames[*]%.pub}"배열의 각 파일 이름으로 구성된 단일 문자열로 확장되고 filenames공백(또는 첫 번째 문자가 무엇 $IFS이든 기본적으로 공백) 으로 구분되며 .pub각 파일 이름에서 접미사 문자열을 제거합니다.

"${filenames[*]}"공백으로 구분된 문자열로 확장되는 비트와 %.pub각 파일 이름에서 접미사를 제거하는 비트 입니다 ..pub

답변2

$res명령 대체는 쉘에 의해 수행됩니다. 값에 슬래시가 있으면 sed는 그것이 명령의 끝이 아니라는 것을 알 수 없습니다 s. 마찬가지로 sed는 백슬래시나 & 기호를 $res특수 문자로 해석합니다 .

백슬래시와 앰퍼샌드를 사용할 수 없고 $res다른 문자도 사용할 수 없다는 것을 알고 있는 경우 해당 문자를 구분 기호로 사용하십시오. 예를 들어:

sed  "s~@demo_project_users = .*~$res~g" example.conf

또는 특수 문자 앞에 백슬래시를 추가하여 인용하십시오.

quoted_res=$(printf %s "$res" | sed 's/[\\\/&]/\\&/g')
sed  "s/@demo_project_users = .*/$quoted_res/g" example.conf

관련 정보