나는 종종 git 저장소를 복제한 다음 해당 루트 디렉터리로 이동합니다. 예를 들어:
$ git clone https://github.com/hpjansson/chafa && cd chafa
cc
이를 좀 더 쉽게 만들기 위해 다음과 같이 확장되는 zsh 약어가 있습니다 && cd !#:2:t
.
typeset -Ag abbrev
abbrev=(
'G' '| grep -v grep | grep'
'L' '2>&1 | less'
'V' '2>&1 | vipe >/dev/null'
'ac' '| column -t'
'bl' '; tput bel'
'cc' '&& cd !#:2:t'
'fl' "| awk '{ print $"
'ne' '2>/dev/null'
'pf' "printf -- '"
'sl' '>/dev/null 2>&1'
'tl' '| tail -20'
)
__abbrev_expand() {
emulate -L zsh
setopt EXTENDED_GLOB
local MATCH
LBUFFER=${LBUFFER%%(#m)[a-zA-Z]#}
if [[ "${LBUFFER: -1}" == ' ' ]]; then
LBUFFER+=${abbrev[$MATCH]:-$MATCH}
if [[ $MATCH = 'fl' ]]; then
RBUFFER="}'"
elif [[ $MATCH = 'pf' ]]; then
RBUFFER="\n'"
fi
else
LBUFFER+=$MATCH
fi
zle self-insert
}
zle -N __abbrev_expand
bindkey ' ' __abbrev_expand
bindkey -M isearch ' ' self-insert
!#
man zshexpn
(섹션 HISTORY EXPANSION
, 하위 섹션 Event Designators
) 에 설명된 대로 현재 명령줄을 참조합니다 .
!#
지금까지 입력된 현재 명령줄을 확인하세요. 줄은 따옴표가 있는 줄 앞의 단어까지 포함하여 완전한 것으로 간주됩니다!#
.
:2
명령줄의 두 번째 단어를 참조합니다(명령어를 입력할 때의 URL입니다 $ git clone
).
n
n번째 매개변수입니다.
그리고 :t
단어의 끝을 나타냅니다.
t
모든 선행 경로 이름 구성 요소를 제거하고 후행 구성 요소는 그대로 둡니다. 마치basename
.
일반적으로 git clone
명령줄에 입력한 다음 프로젝트의 URL을 복사하여 붙여넣고 공백을 삽입한 다음 cc
또 다른 공백을 삽입하면 원하는 명령이 제공됩니다.
하지만 복사하여 붙여넣은 URL이 확장자로 끝나는 경우가 있습니다 .git
. 이런 일이 발생하면 확장자에 !#:2:t
원치 않는 확장자가 포함됩니다 .git
.
$ git clone https://github.com/hpjansson/chafa.git cc
→
$ git clone https://github.com/hpjansson/chafa.git && cd !#:2:t
→
$ git clone https://github.com/hpjansson/chafa.git && cd chafa.git
cd: no such file or directory: chafa.git
:r
한 가지 해결책은 수정자를 사용하여 .git
확장을 제거하는 것입니다.
r
파일 확장자를 제거하고 루트 이름을 유지하십시오. 파일 확장자가 없는 문자열은 변경되지 않습니다. 파일 확장자 뒤에는 둘 다 아닌.
임의 개수의 문자(0 포함)가 오고 문자열 끝까지 계속됩니다. 예를 들어, 확장자는 is 이고 확장자가 없습니다..
/
foo.orig.c
.c
dir.c/foo
vv
$ git clone https://github.com/hpjansson/chafa.git && cd !#:2:t:r
→
$ git clone https://github.com/hpjansson/chafa.git && cd chafa
.git
그러나 경로가 확장으로 끝나지 않으면 확장이 실패하고 git
명령이나 cd
명령이 모두 실행되지 않습니다.
다음은 문제를 설명하는 최소한의 예입니다.
$ echo /foo/bar.baz !#:1:t:r
/foo/bar.baz bar
$ echo /foo/bar !#:1:t:r
zsh: modifier failed: r
첫 번째 명령은 마지막 경로 구성 요소에 확장자가 포함되어 있기 때문에 성공 .baz
하지만 두 번째 명령은 더 이상 확장자가 없기 때문에 실패합니다. OTOH는 bash에서 4.3.48
두 명령 모두 예상대로 작동합니다.
:r
문서에 다음 문장이 포함되어 있기 때문에 확장 없이는 왜 실패하는지 이해할 수 없습니다 .
파일 확장자가 없는 문자열은 변경되지 않습니다.
:r
확장자 없이 문자열을 사용하는 것이 잘못되었다는 의미는 아닙니다 .
확장자를 제거하기 위해 수정자를 사용하는 또 다른 접근 방식을 시도했습니다 :s
. 내 생각에는 다음과 HIST_SUBST_PATTERN
같은 옵션 설정이 필요하다고 생각합니다.
setopt HIST_SUBST_PATTERN
이 옵션을 사용하면 확장자를 제거하기 위해 쓸 수 있습니다 :s/.*
.
vvvvv
$ echo /foo/bar.baz !#:1:t:s/.*
/foo/bar.baz bar
확장이 있으면 작동하지만 확장이 없으면 다시 실패합니다.
$ setopt HIST_SUBST_PATTERN
$ echo /foo/bar !#:1:t:s/.*
zsh: substitution failed
bar
/foo/bar.baz
in 과 to in 을 모두 참조할 수 bar
있는 단일 수정자 시퀀스가 있습니까 /foo/bar
?
나는 그것을 사용하고 있습니다 zsh 5.7.1-dev-0 (x86_64-pc-linux-gnu)
.
답변1
기록 확장을 통해 이를 수행할 수 있는 방법이 생각나지 않습니다. 그러나 나는 히스토리 확장이 최고의 도구라고 생각하지 않습니다. 이것은 매우 제한적입니다. 에서링글 위젯를 사용하면 명령줄에 액세스하여 임의의 코드로 작업할 수 있습니다. 이것을 활용하십시오.
한 가지 방법은 약어를 확장하는 것입니다. $abbrev[$MATCH]
대체를 사용하십시오 ${(e)abbrev[$MATCH]}
. 분명히 특수 문자를 올바르게 참조하려면 약어를 변경해야 합니다. 의 경우 cc
다음과 같은 것을 사용하십시오.
&& cd ${${(z)BUFFER}[3]}
의 특정 경우 git clone
및 보다 일반적으로 현재 디렉토리 내에 디렉토리를 생성하는 모든 경우에는 다른 약어를 사용할 수 있습니다. 새로 생성된 디렉토리로 전환합니다. git clone https://example.com/foo.git
, for git clone https://example.com/foo
및 for git clone https://example.com/foo.git bar
뿐만 아니라 for tar xf foo.tar
(아카이브에 최상위 디렉토리가 있는 경우) 및 에서도 작동합니다 mv /some/directory .
.
&& cd *(/oc[1])