zsh 완성 함수 내에서 작은따옴표가 포함된 파일 이름을 처리하는 방법은 무엇입니까?

zsh 완성 함수 내에서 작은따옴표가 포함된 파일 이름을 처리하는 방법은 무엇입니까?

저는 zsh쉘을 사용하고 있으며 내부에 다음 코드가 있습니다 .zshrc.

fpath=(~/.zsh/completion $fpath)
autoload -Uz _vc

autoload -Uz compinit
compinit

~/.zsh/completion첫 번째 줄은 환경 변수 내에 저장된 배열에 경로를 추가합니다 fpath.

_vc두 번째 줄은 이라는 사용자 정의 셸 함수에 대한 이라는 완성 함수를 로드합니다 vc. 의 목적은 vc단순히 특정 폴더( ~/.cheat) 내의 파일을 편집하는 것입니다. _vc파일에 정의되어 있습니다 ~/.zsh/completion/_vc.

마지막 2줄은 완성 시스템을 활성화합니다.

내 완성 기능에 대한 코드는 다음과 같습니다 _vc.

#compdef vc

declare -a cheatsheets
cheatsheets="$(ls ~/.cheat)"
_arguments "1:cheatsheets:(${cheatsheets})" && return 0

이것부터 복사했어요주소, 내 필요에 맞게 조정했습니다.

디렉터리에 ~/.cheat이름에 작은따옴표가 포함된 파일이 없으면 완성이 작동합니다. 그러나 와 같은 것이 있는 경우 foo'bar다음 오류 메시지와 함께 완료가 실패합니다.

(eval):56: unmatched '
(eval):56: unmatched '
(eval):56: unmatched '
(eval):56: unmatched '

줄의 큰따옴표를 cheatsheets="$(ls ~/.cheat)"작은따옴표로 바꾸는 방법으로 해결책을 찾았습니다 cheatsheets='$(ls ~/.cheat)'.

이제 명령을 실행하면 Tabzsh 는 (zsh가 작은따옴표를 자동으로 이스케이프 처리한 것 같습니다)를 포함하여 vc내부 파일을 제안합니다 .~/.cheatfoo\'bar

그러나 나는 그것이 어떻게, 왜 작동하는지 이해하지 못합니다. 작은따옴표를 사용하면 변수 cheatsheetssould에 리터럴 문자열이 포함됩니다. 따라서 $(...)명령 대체를 확장해서는 안 됩니다. 예를 들어, 다음 명령을 실행하면:

myvar='$(ls)'
echo $myvar    →    outputs `$(ls)` literally

그렇다면 왜 '$(ls ~/.cheat)'내부가 확장 됩니까 _arguments "1:cheatsheets:(${cheatsheets})" && return 0? 그리고 내부의 작은따옴표를 자동으로 이스케이프 처리하는 이유는 무엇입니까 foo'bar?

답변1

우리가 일을 고집한다면 The Wrong Way™

#compdef vc

declare -a cheatsheets
cheatsheets=(${(f)"$(ls ~/.cheat/)"})
_arguments '1:cheatsheets:(${cheatsheets})' && return 0

왝! 물론 이것은 파일 이름에 개행 문자가 포함되어 있으면 중단됩니다 (f).파싱은 ls어쨌든 나쁜 생각이다; ZSH는 파일을 배열에 직접 glob할 수 있습니다.

% mkdir ~/.lojban
% touch ~/.lojban/{go\'i,na\ go\'i}
% words=(~/.lojban/*) 
% print -l ${words:t}
go'i
na go'i
% words=(~/.lojban/*(On))
% print -l ${words:t}    
na go'i
go'i
% 

하지만 아마도 로컬 배열은 필요하지 않을 것입니다. _filesglob에서 완료할 수 있습니다.

#compdef vc
_arguments '1:cheatsheets:_files -g "~/.cheat/*"' && return 0

이는 정규화된 파일 경로를 반환합니다. 검색 디렉터리에서 기본 파일 이름만 필요한 경우 대신 다음을 사용할 수 있습니다.

#compdef vc
_arguments '1:cheatsheets:_files -W ~/.cheat' && return 0

관련 정보