전체 줄이 아닌 특정 문자나 패턴에서 다른 특정 문자나 패턴으로 문자열을 파악하고 싶습니다.
예를 들어:
$ > echo "The brown fox jumps over the lazy dog" | grep -option "b" "s"
brown fox jumps
$ > echo "The brown fox jumps over the lazy dog" | grep -option "the l" "g"
the lazy dog
실제로 필요한 것은 dirs -v
다음을 수행할 수 있도록 경로를 탐색할 때입니다.
$ > ls -AF
file.txt github/ .vim/
$ > dirs -v
0 ~
1 ~/.vim/pack/themes
2 ~/.vim/colors
3 ~/github/dirname
4 ~/github/repo/
$ > mv -v file.txt $(dirs -v | grep 2 | grep -option "~" "colors")
renamed 'file.txt' -> '~/.vim/colors/file.txt'
~
포함된 행만 일치시킬 수 있도록 grep을 두 번 사용했습니다 2
. 내 .zshrc에서 셸 함수/별칭으로 이를 수행할 수 있는 방법이 있나요?
mv file.txt ~2
답변: 저는 아래 답변 중 하나를 사용했습니다 . 제가 이런 일을 할 수 있을 거라고는 생각도 못했어요, 하하.
또한 아래 답변 중 하나의 줄을 .zshrc에 넣었습니다.
function grepo () { grep -Po "${1}.*?${2}" }
alias -g GO='| grepo'
이렇게 하면 다음과 같이 사용할 수 있습니다.
$ > echo "the brown fox jumps over the lazy dog" GO b s
brown fox jumps
$ > echo "the brown fox jumps over the lazy dog" GO "the l" g
the lazy dog
$ > echo "the brown fox jumps over the lazy dog" GO fox over
fox jumps over
내 문제로는 작동하지 않지만 어떤 이유로 생각할 수 없습니다.
$ > ls -AF
file.txt github/ .vim/
$ > dirs -v
0 ~
1 ~/.vim/pack/themes
2 ~/.vim/colors
3 ~/github/dirname
4 ~/github/repo/
$ > mv file.txt $(dirs -v GO "~/.v" "themes")
mv: cannot move 'file.txt' to '~/.vim/pack/themes': No such file or directory
답변1
에서는 zsh
다음을 수행할 수 있습니다.
$ str='The brown fox jumps over the lazy dog'
$ print -r -- ${(SM)str#b*s}
brown fox jumps
ksh ${str#pattern}
연산자 삭제가장 짧은pattern
문자열의 시작 부분부터 일치하는 문자열입니다. ( S
을 위한하위 문자열)매개변수 확장 플래그패턴이 일치에만 국한되지 않도록 확장처음에, 그러나 처음부터 최대한 가깝게. 플래그 M
(용일치)는 이러한 확산 연산자가 일치하는 부분을 제거하는 대신 일치하는 콘텐츠로 확장되도록 합니다.
당신을 허락하는 ##
대신에 사용하세요#
가장 긴바꾸다가장 짧은및 %
/ %%
문자열 끝에서 패턴을 찾습니다.
*?
PCRE 일치를 수행하고 탐욕스럽지 않은 연산자를 사용할 수도 있습니다 .
$ zmodload zsh/pcre
$ [[ $str -pcre-match 'b.*?s' ]] && print -r -- $MATCH
brown fox jumps
또는:
$ set -o rematchpcre
$ [[ $str =~ 'b.*?s' ]] && print -r -- $MATCH
brown fox jumps
하지만 특정 사용 사례에서는 다음과 같이 합니다.
mv file.txt ~2
파일을 디렉터리 스택의 두 번째 디렉터리로 이동합니다.
구성이 올바른 경우 이후를 누르면 완료 시 ~<number>
다음 내용에 해당하는 내용이 표시됩니다.Tab~+
$ MV 파일~+Tab 완전한 디렉토리 스택 1 -- ~/install/cvs/zsh/Config 2 -- ~ 3 -- /usr 4 -- ~빈 5 -- ~ 6 -- /
~/.zshrc
이 출력을 생성하는 최소값은 다음과 같습니다.
set -o autopushd
autoload -Uz compinit
compinit
zstyle ':completion:*' menu select=0
zstyle ':completion:*' verbose true
zstyle ':completion:*' format 'Completing %d'
compinstall
( 초보자 친화적인 방식으로 마감 사용자 정의 참조 )
답변2
PCRE 정규식에서 지연 일치를 사용합니다( .*?
).
$ str='The brown fox jumps over the lazy dog'
$ grep -Po 'b.*?s' <<<"$str"
brown fox jumps
$ grep -Po 'the l.*?g' <<<"$str"
the lazy dog
보다 기본적인 정규식에 대한 유사한 솔루션이 있지만 단일 문자에만 해당됩니다(오른쪽).
$ grep -o 'b[^s]*s' <<<"$str"
brown fox jumps
$ grep -o 'the l[^g]*g' <<<"$str"
the lazy dog
위의 항목이 모두 일치합니다.첫 번째초기 텍스트 이후첫 번째최종 텍스트(포함).
답변3
이를 수행하는 더 쉽고 안정적인 방법이 있습니다.
zsh에서, 사용dirstack
바꾸다. zsh는 변수 확장에 대해 멋진 작업을 수행하지 않기 때문에 인용이 필요하지 않습니다.
mv file.txt $dirstack[2]
상위 디렉토리를 원하면 추가할 수 있습니다.기록 수정자 :h
. 예를 들어 파일을 디렉터리 스택 항목의 상위 항목으로 이동하려면 를 사용합니다 mv file.txt $dirstack[2]:h
. 파일을 상위 항목의 상위 항목으로 이동하려면 mv file.txt $dirstack[2]:h:h
또는 를 사용합니다 mv file.txt $dirstack[2]:h2
.
당신은 또한 사용할 수 있습니다매개변수 확장디렉토리 이름을 수정하기 위해 구성하지만 더 복잡해집니다.
또는 대상 디렉토리를 수정하려면 after를 누르면 Tabzsh $dirstack[2]
가 변수 확장을 해당 값으로 바꿉니다.
배쉬에서, 사용DIRSTACK
바꾸다. 따옴표와 중괄호가 필요합니다.
mv file.txt "${DIRSTACK[2]}"
당신은 사용할 수 있습니다매개변수 확장결과 값을 기반으로 빌드합니다. 예를 들어 파일을 디렉터리 스택 항목의 상위 디렉터리로 이동하려면 mv file.txt "${DIRSTACK[2]#/*}"
.
$ > mv -v file.txt $(dirs -v | grep 2 | grep -option "~" "colors")
깨지기 쉽습니다. 디렉토리 이름에 2
?가 포함되어 있거나 스택에 12개 이상의 디렉토리가 있는 경우? 명령 대체 결과 물결표가 확장되지 않기 때문에 작동하지도 않습니다. 당신은 다음과 같은 것을 사용해야합니다
"$(HOME=/none dirs -v | grep '^ *2[^0-9]' | sed 's:^[^/]*::')"
- 큰따옴표로 명령 대체를 묶습니다.생성된 디렉터리 이름에 공백이 포함된 경우.
2
줄의 시작 부분에서만 일치합니다(선행 공백은 허용됩니다).2
여러 자리 숫자의 앞자리이면 일치하지 않습니다.- sed를 사용하여 디렉터리 이름이 시작되기 전의 모든 항목을 삭제하세요.
HOME
런타임 시 존재하지 않는 경로로 설정되므로 디렉터리dirs
이름은 슬래시로 시작하는 것이 보장됩니다. - 디렉터리 이름의 일부만 선택하려는 경우 추가 grep만 있으면 됩니다.
awk가 더 나은 도구일 수도 있지만, 좀 더 일반적인 단일 도구(awk)를 사용할지 아니면 좀 더 전문화된 도구(grep, sed 등)의 조합을 사용할지는 어느 정도 취향의 문제입니다.
"$(HOME=/none dirs -v | awk '$1 == 2 {sub(/^[ \t0-9]+/, ""); print; exit}')"
1완성 및 키 바인딩 설정에 따라 다른 키가 필요할 수 있습니다. 가능성에 대해 논의하는 것은 이 답변의 범위를 벗어납니다.
²빈 단어를 제거하는 것을 제외 하고는 디렉토리 스택이 충분히 깊은지 확인하는 한 문제가 되지 않습니다.
³ 디렉터리 이름에 공백(또는 와일드카드)이 포함되어 있지 않으면 따옴표가 필요하지 않습니다.