한 문자나 패턴에서 다른 문자나 패턴으로 이동하는 방법은 무엇입니까?

한 문자나 패턴에서 다른 문자나 패턴으로 이동하는 방법은 무엇입니까?

전체 줄이 아닌 특정 문자나 패턴에서 다른 특정 문자나 패턴으로 문자열을 파악하고 싶습니다.

예를 들어:

$ > 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완성 및 키 바인딩 설정에 따라 다른 키가 필요할 수 있습니다. 가능성에 대해 논의하는 것은 이 답변의 범위를 벗어납니다.
²빈 단어를 제거하는 것을 제외 하고는 디렉토리 스택이 충분히 깊은지 확인하는 한 문제가 되지 않습니다.
³ 디렉터리 이름에 공백(또는 와일드카드)이 포함되어 있지 않으면 따옴표가 필요하지 않습니다.

관련 정보