Bash:stdoutの最後(またはN番目)の行をキャプチャ/使用


11

問い合わせ

私はBashを使用しています。ファイルを探すときは、多くの場合、次のことを行います。

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:結果リストのN番目のアイテムをvimで開きます。

現在、マウスでカットアンドペーストしています。これは私に私の質問をもたらします:

  1. オプション1と2を実現する簡単なワンライナーはありますか?これはコマンドのに発生していることに注意してくださいfind
  2. ある種のbashベクトル/配列で標準出力からN行をキャプチャする方法はありますか?

理想的な使い方

$ 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)

(構文とセマンティクスは異なる場合がありますが、要点はわかります)

Similaria

同様の質問がいくつかあるようです。ここに私の認識された違いがあります(私は悟りに開いています):

ご協力ありがとうございました!私が90年代の10代のときに* nix / BSDを使用していて、プラグアンドプレイサウンドカード用のドライバーをインストールするのに役立つように燃え尽きてアシッドヘッドの隣人を呼んで怖がってしまったので、コマンドについて話し合うと安心しました。 (恐らく)恐ろしい個人が少ない特徴点を並べます。戻ってきて気持ちいいです。


最後の結果を開きたいという前にそれを知っているなら、あなたはのようなものを使うことができると思いvim $(command |tail -n1)ます。
varesa 2013年

私はここに同様の質問を投稿unix.stackexchange.com/questions/348224/...
joelostblom

回答:


8

ファンキーなファイル名が存在する場合に合理的に(ただし完全ではない)安全である必要がある問題の潜在的な解決策を次に示します(改行が含まれているファイル名は処理しません-おそらく修正可能ですが、他の問題が潜んでいる可能性があります)。

2つの関数、最初の関数は、find渡したパラメーターで実行され、出力を配列に保存して表示します。2番目は、その配列にアクセスするためのヘルパーです。

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
評判が足りないので賛成できません。口頭の言葉は次のとおりです。「
賛成

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の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コマンド」を使用してスクリプトを呼び出します。ここにスクリプトを呼び出すコードを示します。

./autofind `your find command`

ただし、スクリプトを使用する前に、「findコマンド」で結果が出ているかどうかを確認してください。結果が表示されている場合は、スクリプトのみを使用してください。


0

マットの答えは私が探していたものでした。私は彼のコードを少し拡張して、より多くのgetオプションを可能にしました。

$ 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.