배쉬 : 캡처 / stdout에서 마지막 (또는 N 번째) 라인 사용


11

질문

나는 배쉬를 사용한다. 파일을 찾을 때 종종 다음을 수행합니다.

find -name stackexchange.hs

그리고 종종 결과는 다음과 같습니다.

/youre/the/man/now/dog/stackexchange.hs
/you/are/no/longer/the/dog/dog/stackexchange.hs
/this/is/the/file/i/want/stackexchange.hs

그런 다음 다음 중 하나를 수행하고 싶습니다.

  • 옵션 1 : vim 의 결과 목록에서 마지막 항목을 엽니 다 .
  • 옵션 2 : vim 의 결과 목록에서 N 번째 항목을 엽니 다 .

현재는 마우스로 잘라 붙여 넣기를합니다. 내 질문에 나를 가져옵니다 .

  1. 옵션 1 & 2를 달성하기 쉬운 하나의 라이너가 있습니까? 이것은 명령 후에 발생 합니다 find.
  2. 일종의 bash 벡터 / 배열에서 stdout에서 N-line을 캡처하는 방법이 있습니까?

이상적인 사용법

$ find -name am_i_really_all_alone.txt
./borges/library/you_are_not_alone.txt
./borges/library/am_i_really_all_alone.txt
$ vim (N)

(구문과 의미가 다를 수 있지만 요점을 알 수 있습니다)

비슷한

몇 가지 비슷한 질문이있는 것 같습니다. 여기에 내가 인식 한 차이점이 있습니다 (깨달음이 열려 있습니다).

도와 주셔서 감사합니다! 90 년대에 10 대 때 * nix / BSD를 사용하고 플러그 앤 플레이 사운드 카드 용 드라이버 설치를 도와주는 소실 된 이웃집에 전화를 걸면 겁에 질려서 덜 무시 무시한 개인이있는 (분명히) 줄을 줄입니다. 돌아와서 기분이 좋아.


마지막 결과를 열기 전에 알고 있다면 다음과 같은 것을 사용할 수 있다고 생각 vim $(command |tail -n1)합니다.
varesa

나는 비슷한 질문을 여기에 게시했다. unix.stackexchange.com/questions/348224/…
joelostblom

답변:


8

다음은 펑키 한 파일 이름 이있을 때 합리적으로 (완벽하지는 않지만) 안전 해야하는 잠재적 인 해결책 입니다 (줄 바꿈이 포함 된 파일 이름을 처리하지 않음-수정 가능하지만 숨기는 다른 문제가있을 수 있음).

첫 번째 기능은 find전달한 매개 변수로 실행 되고 출력을 배열에 저장 한 후 표시하는 두 가지 기능 입니다. 두 번째는 해당 어레이에 액세스하는 도우미입니다.

myfind() {
  IFS=$'\n' __last_find_result=($(find "$@"));
  printf "%s\n" "${__last_find_result[@]}";
}
myget() {
  echo "${__last_find_result[$1]}";
}

사용 사례 :

$ myfind . -name "c*"
./a b/c d
./.git/config
./.git/hooks/commit-msg.sample
$ vim "$(myget 0)"
# This opens the "./a b/c d" file.
$ vim "$(myget 2)"
# This opens ".git/hooks/commit-msg.sample"

$(myget index)파일 이름에 공백이나 다른 성가신 문자가 없으면 따옴표가 필요 하지 않습니다.
전체 출력을 find환경으로 푸시합니다 ( 제한 될 수 있음). (해당 배열 대신 임시 파일을 사용하면 문제를 해결할 수 있지만 여러 셸에서 동시에 사용하는 다른 문제가 있습니다.)


1
나는 평판이 충분하지 않아서 당신을 옹호 할 수 없습니다. 그래서 여기에 구두가 있습니다 : "upvote"
aaronlevin

6

나는 이것을 내 안에 가지고있다 .screenrc:

bind -c pasteline 1 eval copy 'stuff "-Y"' 'paste .'
bind -c pasteline 2 eval copy 'stuff "2-Y"' 'paste .'
bind -c pasteline 3 eval copy 'stuff "3-Y"' 'paste .'
bind -c pasteline 4 eval copy 'stuff "4-Y"' 'paste .'
bind -c pasteline 5 eval copy 'stuff "5-Y"' 'paste .'
bind -c pasteline 6 eval copy 'stuff "6-Y"' 'paste .'
bind -c pasteline 7 eval copy 'stuff "7-Y"' 'paste .'
bind -c pasteline 8 eval copy 'stuff "8-Y"' 'paste .'
bind -c pasteline 9 eval copy 'stuff "9-Y"' 'paste .'
bindkey ¬ command -c pasteline

기본적으로 화면에서 ¬1, 커서 위에 줄을 ¬2붙여넣고, 커서 위에 두 번째 줄을 붙여 넣습니다. 10 줄 이상을 더 추가하고 싶을 수도 있지만, 약 7 후에 이미 원하는 screen줄을 얻기 위해 줄 수를 세는 것보다 마우스 또는 복사 모드를 사용하고 싶습니다.


0

또 다른 해결책은 자동으로 선택을 요구하는 대화식 스크립트를 작성할 수 있습니다. 대화식 스크립트 코드는 다음과 같습니다.

#!/bin/bash

echo "enter your choice : z for last argument or a number for that file"
read choice

case "$choice" in
z) eval vim \$$#;;
*)eval  vim \$$choice;;
esac

이 스크립트를 "autofind"라는 이름으로 저장하고 "find command"를 사용하여 스크립트를 호출하십시오. 인수는 스크립트를 호출하는 코드입니다.

./autofind `your find command`

그러나 스크립트를 사용하기 전에 "find command"가 결과를 제공하는지 여부를 확인하십시오. 결과가 표시되면 스크립트 만 사용하십시오.


0

매트 답변은 내가 찾던 것입니다. 더 많은 get-options을 허용하기 위해 그의 코드를 약간 확장했습니다.

$ f ~/scripts -name '*.sh'
$ vim $(g foo)  # edit all find results matching "foo"
$ vim $(g 1 3 5) # edit find results number 1, 3 and 5
$ vim $(g 3-5) # edit find results 3-5
$ vim $(g 5-) # edit find results 5 to last
$ vim $(g -7) # edit find result 7 from bottom
$ vim $(g 1 4-5 -7 9- foo) # all of the above combined

.

f() {
    IFS=$'\n' __last_find_result=($(find "$@"));
    printf "%s\n" "${__last_find_result[@]}";
}

g() {
    len=${#__last_find_result[@]}
    pad=${#len}
    numbers=""
    if [ "$1" == "-n" ]; then
        numbers=1
        shift
    fi
    if [ -z "$1" ]; then
        if [ -n "$numbers" ]; then
            n=1;
            for e in "${__last_find_result[@]}";do
                printf "%0${pad}d. %s\n" "$n" "$e"
                let n=n+1
            done
        else
            printf "%s\n" "${__last_find_result[@]}"
        fi
    else
        for l in $@;do
            if [[ "$l" =~ ([^0-9-]+) ]];then
                n=1;
                for e in "${__last_find_result[@]}";do
                    if [[ $e =~ $1 ]]; then
                        if [ -n "$numbers" ];then
                            printf "%0${pad}d. %s\n" "$n" "$e"
                        else
                            printf "%s\n" "$e"
                        fi
                    fi
                    let n=n+1
                done
            elif [[ "$l" =~ ^([0-9]+)$ ]];then
                let l=l-1
                echo "${__last_find_result[$l]}";
            elif [[ "$l" =~ ^([0-9]*)(-)?([0-9]*)$ ]]; then
                from=${BASH_REMATCH[1]};
                dash=${BASH_REMATCH[2]};
                to=${BASH_REMATCH[3]};
                if [ -z "$from" ]; then # -n
                    [ $to -gt ${#__last_find_result[@]} ] && to=${#__last_find_result[@]}
                    echo "${__last_find_result[-$to]}";
                else # n-m
                    [ -z "$to" ] && to=${#__last_find_result[@]}
                    [ $to -gt ${#__last_find_result[@]} ] && to=${#__last_find_result[@]}
                    let to=$to-1
                    let from=$from-1
                    n=$(($from+1))
                    for i in `seq $from $to`;do
                        if [ -n "$numbers" ];then
                            printf "%0${pad}d. %s\n" "$n" "${__last_find_result[$i]}"
                        else
                            printf "%s\n" "${__last_find_result[$i]}"
                        fi
                        let n=n+1
                    done
                fi
            fi
        done
    fi
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.