コマンドラインからの最後の出力を再利用するにはどうすればよいですか?


43

コンソールからの最後の出力を再利用する方法を知りたい、すなわち:

pv-3:method Xavier$ python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/Library/Python/2.6/site-packages
pv-3:method Xavier$ cd **LASTOUTPUT**

7
できません。ここに背景の説明があります。これまでに投稿された2つの回答に見られるように、最善の策はコマンドを再度実行することです。
ジル 'SO-悪

などのデバイスに直接送信された出力をキャプチャすることはできません/dev/ttyが、stdoutまたはstderrに送信されたものなら何でもキャプチャできるはずです。
ミケル

@Gilles-@mattdmの回答を使用しない限り、もちろんです!
サイモン

@Gilles:ただし、コマンドの出力をキャプチャ(およびパススルー)し、キャプチャした出力をユーザーが他のコマンドから参照できるようにする誰かによって作成されたシェルが存在する場合があります。おそらく、...でも多かれ少なかれ合併症でこれを許可するいくつかの既存の、それほど人気がないシェルがある
IMZ -イワンZakharyaschev

回答:


39

bashを想定:

% python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/usr/lib/python2.7/site-packages
% cd $(!!)
cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
% pwd
/usr/lib/python2.7/site-packages

1
ありがとう!入力するのは簡単ではありませんが、マウスの操作に勝るものはありません。
methodofaction

2
また、$()の代わりにバックティック(このインターフェイスをwikiにできないようにする方法がわかりません)を使用することもできますが、backtick-shift-1-shift-1-backtickを押すのは不快であることがわかりました、そして、読みやすくするために、可能な場合は$()を使用する習慣になろうとしています。
jsbillings

@jsbillingsは、以下の私の答えを参照してください。答えに `を表示するために\`と入力しました。また、「\」を表示するには、通常どおり「\\」と入力します。
yasouser

3
+1巣を作る方法について疑問に思っています`backtick-commands`cd $(dirname $(which python))俺様の登場だ!
エドブラニン

21
ただし、これはコマンドを再実行していることに注意してください。コマンドに副作用がある場合、これはうまくいかない可能性があります。
リッチホモルカ

13

まだ言及していませんが、変数を使用してください:

dir=$( python -c ... )
cd "$dir"

3
まさに。シェルであるため、ループや割り当てなど、Bashが提供する言語機能を忘れることがよくあります。
エヴァン

言うことができますcd $dir
temporary_user_name

3
:@Aerovistae、引用符は、値がどこから来るのかがわからない場合に必要とされている
グレン・ジャックマン

@glenn、(これは他のすべての質問かもしれませんが、答えが短い場合:)引用符を使用しないと物事が壊れる例を説明/提供できますか?
アレクセイ


8

他のすべてのソリューションには、ワークフローの変更またはコマンドの2回の実行が含まれます。これは、実行に時間がかかる場合や繰り返しできない場合(たとえば、ファイルを削除する-再実行すると異なる結果が生じる)には適さない場合があります。

必要な場合は、より複雑なアイデアを以下に示します。

.bashrc

exec > >(tee -a ~/$$.out)

PROMPT_COMMAND='LASTLINE=$(tail -n 1 ~/$$.out)'

trap 'rm ~/$$.out' EXIT

bashプロンプト

$ python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/usr/lib/python2.6/dist-packages
$ cd $LASTLINE
$ pwd
/usr/lib/python2.6/dist-packages

これにはいくつかの問題があるので、それは出発点としてのみ意味されます。たとえば、出力ファイル(~/<pid>.out)が非常に大きくなり、ディスクがいっぱいになる場合があります。また、tee死んだ場合、シェル全体が動作しなくなる可能性があります。

zshのpreexecand precmdフックを使用して前のコマンドからの出力のみをキャプチャするように変更することも、bash でそれらのエミュレーションをキャプチャすることもできますが、ここで説明するのはより複雑です。


6
基本的な考え方は良いのですが、実装はそうではありません。シェルセッションの標準出力は端末ではなくパイプであり、一部のプログラムの動作が異なります。stdoutへの書き込みとstderrへの書き込みまたはttyへの直接書き込みは同期されないため、たとえば、次のプロンプトの後にコマンド出力が表示される場合があります。またtee、シグナルから保護されていません(Ctrl+Cいくつかのコマンドを押して実行してみてください)。scriptこれらの問題のないユーティリティを使用してください。
ジル「SO-悪であるのをやめる」

知っておきたい!私はまだコマンドラインの基本に取り組んでいるので、これは私にとってはやり過ぎかもしれません。さらに、任意のコンピューターで使用できるようにしたいのですが、良いレベルに達した場合は覚えています。
methodofaction

8

従来のシェルの作業ドラフト:

ttyid=$(readlink /proc/$$/fd/1)
\___/   \______/ \___/ |  |  |
  |         |      |   |  |  \- 0: stdin 
  |         |      |   |  |     1: stdout <- our interest
  |         |      |   |  |     2: stderr
  |         |      |   |  \- fd is, maybe, filedescriptor
  |         |      |   |
  |         |      |   \- $$ is the PID of the current process (shell,
  |         |      |      in our case)
  |         |      |
  |         |      \- you know, much runtime stuff is here
  |         |
  |         \- readlink extracts the symbolic link of /proc/$$/fd/1
  |            lrwx------ 1 stefan stefan 64 2011-03-18 09:11
  |            /proc/22159/fd/1 -> /dev/pts/4
  |
  \- /dev/tty3 for real shell, /dev/pts/3 for xterm

これで、画面をファイルに接続できます。sudoが必要です。

id=${ttyid//\/dev\/tty}
sudo cat /dev/vcs$id > screen.dump

Apropos screendump:そのため、名前の付いたプログラムはもう機能しません。おそらく古いカーネルのみ。/ dev / pts / Nも私には機能しませんでした。/ devにあるオプションのMKDEVが必要な/dev/cuaN場合があります。一部については暗く覚えていますが、間違っている可能性があります。

screen.dumpを使用する代わりに出力をパイプしたいと思います。しかし、どういうわけか機能しません-時にはENTERを待ちます。

キャプチャは、改行を含む通常のテキストファイルではなく、たとえば、1つのシーケンスで80x50文字を使用します。

最後の2行(コマンドの出力用とプロンプト行用)を選択するには、それを元に戻し、160文字を選択し、再び元に戻し、80を選択します。

rev vcs4.dat | sed 's/\(.\{160\}\).*/\1/g' | rev | sed 's/\(.\{80\}\).*/\1/g'

あなたが疑問に思った場合に備えて、なぜrevプログラムがあるのか。

批評:

  • 最初のコマンドが入力されるため、行が移動します。さて-最後の3行目か何かを選ぶための単なる数値の練習問題です。主に別のウィンドウで作業しました。
  • 誰もが80x50の画面を持っているわけではありません。まあ、はい、知っています。あなたの喜びのために$ COLUMNSと$ ROWSがあります。
  • 出力は常に最下部にあるわけではありません。新鮮で若い貝が上の列にあるかもしれません。さて-簡単です:実行中のシェルを評価します。使用されるプロンプト。プロンプトの検出をいくつか行い、シェルプロンプトで最後の行を見つけます。前の行(または前の2.)にディレクトリが含まれている必要があります。

最初の図は、explain.pyで作成されています


+1、私にさせられましたalias tee2tty='tee $(readlink /proc/$$/fd/1)'
トビアス・キーンズラー

7

これを試して:

$ cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
$ pwd
/Library/Python/2.6/site-packages

6

だから、ええと、ここに答えがあります:

Xで実行している場合は、目的の出力をマウスで選択してコピーし、中クリックして貼り付けます。

テキストコンソールで実行している場合は、gpmを使用して同様の操作を実行できます。


1
+1-良い答え!GNU screen(gnu.org/software/screen)を使用して、Xを実行していない場合でも同じことを実現できます。
サイモン

1
私はそれを言うのをためらっていたほど明白だった。しかし、他のみんなは賢いので忙しいです。:)
mattdm

それはOPができるようになりますここでの唯一の答えだ再利用最後の行を-どこでも全く無関係と壊滅的な:)しかし、OPが言うのでし間の可能性があり再度コマンドを実行している他のすべて伴い、再利用を
サイモン

@simon:実際、私の答えはそうではありません。グレンもしません。
ミケル

@Mikel:はい。ただし、事前に何かをする必要があります。
mattdm

1

(残念ながら、それは有効な答えではありませんが、それでも奇妙なものです。興味のある人は、この記事で紹介する機能の実装を完了することを試みることができます。)

ではeshellEmacsの内部に、彼らは、このような機能を持っていると思ったが、それは(但しされ、完全な形で実装されていないドキュメントに反映します)。

例えば:

~ $ pwd
~
~ $ /bin/echo $$
~
~ $ /bin/pwd
/home/imz
~ $ /bin/echo $$

~ $ 

ビルトインの出力のみを$$変数にキャプチャできます。

しかし、まあ、いくつかのelispプログラミング(eshell-mark-output「esh-mode.el」の実装を参照)、および最後の出力を「マーク」して関数の結果として返す関数を実装できます。求めているeshellコマンドでその関数を使用できるように、elisp関数は通常のelisp構文を使用したeshellコマンドで、つまり次のように括弧で使用できます。

~ $ /bin/echo (buffer-name)
*eshell*
~ $ /bin/echo (car '(a b c))
a
~ $ 

0

ヒットする前に出力を再利用したいEnter場合は、変数に保存することができます。tmp=$(行の先頭と)末尾に追加します。(これにより、コマンド出力の最後の空白行が削除され、実際には最終改行が削除されます。これはめったに問題になりません。)

tmp=$(python -c )
echo "$tmp"
cd "$tmp"

シェルがkshまたはzshの場合、これをより自動化するために使用できる便利な関数を次に示します。(bashでは、親シェルでパイプラインの最後のコマンドを実行する必要がありますが、これはksh(pdkshではない)およびzshでのみ必要なため、役に立ちません。)

keep () {
  local line IFS=$'\n'
  kept=
  while read -r line; do
    printf '%s\n' "$line"
    kept=$kept$line$IFS
  done
}
alias keep=k

次のように使用します。

python -c  |k
cd $kept

0
cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" | tee $(readlink /proc/$$/fd/1))

4485の答え基づいて構築)

それは大量の入力なので、エイリアスを作成します:

alias tee2tty='tee $(readlink /proc/$$/fd/1)'

その後、単に呼び出します cd $(python -c ... | tee2tty)

もちろん、これには出力で何をしたいかをすでに知っている必要がありますが、コマンドを1回だけ呼び出すという利点があります。


0
$ cd \`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"\`

トリックを行います。

詳細については、コマンド置換を参照してください。


1
arumug:bahamatはすでにほぼ同じ回答を投稿しています。コマンドにすでにバッククォートがある場合、バッククォートのあるバージョンが常に機能するとは限りません。
ジル「SO-悪であるのをやめる」

0

より良い解決策があります:

!!コマンドを実行した後に印刷すると、出力が繰り返されます。

例えば

ここに画像の説明を入力してください

元の:

https://askubuntu.com/questions/324423/how-to-access-the-last-return-value-in-bash


!!最後のコマンドの結果を繰り返さず、最後のコマンドを再実行します。jot -r 1 0 10000から1000までの単一の乱数を返す場合、そのコマンドを1回実行してを取得した539後、実行!!すると他の数値が得られる可能性が高くなります。!!前のコマンドの実行にかなりの時間がかかる場合、または繰り返してはならない操作(ファイルの変更など)を繰り返す場合にも望ましくない場合があります。
カレブ

1
ナイスキャッチ。私が間違っていることを証明する簡単な方法がありますが、echo $ RANDOM; !!
テベ

甘い-それについて知らなかった!ありがとう。
カレブ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.