Bash에서 마지막 명령의 출력 재사용


답변:


184

마지막 명령의 출력 $(!!)재 계산 (재사용 아님) 하는 데 사용할 수 있습니다 .

!!자체가 실행의 마지막 명령.

$ echo pierre
pierre
$ echo my name is $(!!)
echo my name is $(echo pierre)
my name is pierre

9
$(your_cmd)백틱을 사용하여 입력하지 `your_cmd`않아도됩니다. Gnu Bash 매뉴얼에 따르면 기능은 동일합니다. 물론이 또한 @memecs에 의해 제기 된 경고의 적용을받습니다

실제로 명령의 출력은 결정론 적이므로 다시 계산하는 것에 대해서는 고민하지 않습니다. git diff $(!!)이전 명령이 find호출 된 곳 과 같은 것을하고 싶을 때 확실히 유용합니다 .
Sridhar Sarnobat

$()백틱 대신에 사용해야 할 이유가 있습니다 . 그러나 아마도 잠을 잃을 것은 없습니다. github.com/koalaman/shellcheck/wiki/SC2006
Michael Crenshaw

1
@ user2065875 backticks는 여전히 Bash에서 작동하지만을 위해 더 이상 사용되지 않습니다 $().
kurczynski

87

내 대답은 아니오 야. Bash는 출력을 메모리의 매개 변수 또는 블록에 할당하지 않습니다. 또한 허용 된 인터페이스 작업을 통해서만 Bash에 액세스 할 수 있습니다. Bash의 개인 데이터는 해킹하지 않으면 액세스 할 수 없습니다.


2
모든 명령 전에 실행되는 일부 사용자 정의 bash 'middleware'기능을 사용할 수 있습니까? 여기서 결과는 내부 클립 보드 역할을하는 무언가 (예 : BASH_CLIPBOARD)에 결과 출력을 저장하는 것입니까?
Pat Needham

@PatNeedham 확실하지 않습니다. 로드 가능한 모듈을 점검하십시오. 글을 쓸 수 있는지보십시오.
konsolebox

11

이를 수행하는 한 가지 방법은 다음을 사용하는 것입니다 trap DEBUG.

f() { bash -c "$BASH_COMMAND" >& /tmp/out.log; }
trap 'f' DEBUG

이제 가장 최근에 실행 된 명령의 stdout 및 stderr은 /tmp/out.log

단점은 명령을 두 번 실행한다는 것입니다. 한 번은 출력과 오류를 리디렉션 /tmp/out.log하고 한 번은 정상으로 리디렉션 합니다. 아마도이 동작을 막을 수있는 방법이있을 것입니다.


10
그래서 내가 입력 rm -rf * && cd ..하면 현재 디렉토리뿐만 아니라 부모 디렉토리도 지워집니다 ?? 이 접근법은 나에게 매우 위험한 것 같습니다
phil294

1
이제이 작업을 어떻게 취소합니까?
Kartik Chauhan

5
@KartikChauhan : 그냥trap '' DEBUG
anubhava

7

mac을 사용하는 경우 변수에 쓰는 대신 출력을 클립 보드에 저장하지 않아도되는 경우 해결 방법으로 pbcopy 및 pbpaste를 사용할 수 있습니다.

예를 들어, 파일을 찾고 다른 파일과 내용을 다르게하기 위해이 작업을 수행하는 대신 :

$ find app -name 'one.php' 
/var/bar/app/one.php

$ diff /var/bar/app/one.php /var/bar/two.php

당신은 이것을 할 수 있습니다 :

$ find app -name 'one.php' | pbcopy
$ diff $(pbpaste) /var/bar/two.php

/var/bar/app/one.php첫 번째 명령을 실행할 때 문자열 은 클립 보드에 있습니다.

그런데, PBpbcopypbpaste스탠드 판지, 클립 보드의 동의어합니다.


1
리눅스에서 $ find app -name 'one.php' | xclip $ diff $(xclip -o) /var/bar/two.php
si-mikey

흥미롭게도, 나는 pbpaste명령 대체와 함께 사용 하는 것을 생각하지 못했습니다 .
Sridhar Sarnobat

첫 번째 작업을 수행 한 후 비효율적이라는 것을 알고 있다면 두 번째 옵션으로 다시 실행하지 않고 계산 시간을 어떻게 절약 할 수 있습니까?
NelsonGon 2016 년

4

anubhava의 대답에서 영감을 얻었습니다. 각 명령을 두 번 실행하므로 실제로 허용되지 않습니다.

save_output() { 
   exec 1>&3 
   { [ -f /tmp/current ] && mv /tmp/current /tmp/last; }
   exec > >(tee /tmp/current)
}

exec 3>&1
trap save_output DEBUG

이렇게하면 마지막 명령의 출력이 / tmp / last에 있고 명령이 두 번 호출되지 않습니다.


1
나는이에 발견 한 한 가지 단점은 당신의 명령의 누구도 그들이 당신 같은 유틸리티의 작업 색상 코드를 얻기 위해 특별한주의가 필요한 의미, 더 이상 청각 장애에서 실행되는 생각하지 않습니다 grep또는 git diff하지만 어쨌든 +1
마티 닐

2

konsolebox가 말했듯이 bash 자체를 해킹해야합니다. 다음 은이를 달성하는 방법에 대한 아주 좋은 예입니다. stderred 저장소 (실제로 stdout을 채색하기위한 것)는이를 빌드하는 방법에 대한 지침을 제공합니다.

새로운 파일 기술자 내부 정의 : 나는 그것을 시도했다 .bashrc등이

exec 41>/tmp/my_console_log

(숫자는 임의적 임) stderred.c내용도 fd 41에 기록되도록 수정하십시오. 일종의 작동하지만 NUL 바이트, 이상한 형식을 포함하고 기본적으로 읽을 수없는 이진 데이터입니다. C에 대해 잘 알고있는 사람이 시도해 볼 수 있습니다.

그렇다면 마지막 인쇄 된 줄을 얻는 데 필요한 모든 것은 tail -n 1 [logfile]입니다.


1

예, 동의 할 때마다 추가 줄을 입력해야하는 이유는 무엇입니까? 리턴 값을 입력으로 리디렉션 할 수 있지만 출력 (1> & 0) 출력은 nope입니다. 또한 각 파일에 동일한 함수를 반복해서 쓰고 싶지 않습니다.

파일을 다른 곳으로 내 보내지 않고 로컬에서만 사용하려는 경우 터미널에서 함수 선언을 설정할 수 있습니다. ~/.bashrc파일이나 파일에 함수를 추가해야 ~/.profile합니다. 두 번째 경우에, 당신은 활성화해야합니다 Run command as login shell에서 Edit>Preferences>yourProfile>Command.

다음과 같이 간단한 기능을 만드십시오.

get_prev()
{
    # option 1: create an executable with the command(s) and run it
    echo $* > /tmp/exe
    bash /tmp/exe > /tmp/out

    # option 2: if your command is single command (no-pipe, no semi-colons), still it may not run correct in some exceptions
    #echo `$*` > /tmp/out

    # return the command(s) outputs line by line
    IFS=$(echo -en "\n\b")
    arr=()
    exec 3</tmp/out
    while read -u 3 -r line
    do
        arr+=($line)
        echo $line
    done
    exec 3<&-
}

기본 스크립트에서 :

#run your command:
cmd="echo hey ya; echo hey hi; printf `expr 10 + 10`'\n' ; printf $((10 + 20))'\n'"
get_prev $cmd
#or simply
get_prev "echo hey ya; echo hey hi; printf `expr 10 + 10`'\n' ; printf $((10 + 20))'\n'"

Bash는 이전 범위 밖에서도 변수를 저장합니다.

#get previous command outputs in arr
for((i=0; i<${#arr[@]}; i++)); do echo ${arr[i]}; done

1

매우 간단한 솔루션

몇 년 동안 사용해온 것.

스크립트 ( .bashrc또는에 추가 .bash_profile)

# capture the output of a command so it can be retrieved with ret
cap () { tee /tmp/capture.out}

# return the output of the most recent command that was captured by cap
ret () { cat /tmp/capture.out }

용법

$ find . -name 'filename' | cap
/path/to/filename

$ ret
/path/to/filename

나는 | cap모든 명령의 끝에 추가하는 경향이 있습니다 . 이렇게하면 느리게 실행되는 명령의 출력에서 ​​텍스트 처리를 원할 때 항상 검색 할 수 있습니다 res.


지점 무엇 cat -cap () { cat - | tee /tmp/capture.out}여기가? cap () { tee /tmp/capture.out }누락 된 딸꾹질이 발생 합니까 ?
왓슨

1
@ 왓슨 좋은 지적! 내가 왜 그런 습관을 가지고 있는지 모르겠습니다. cat - | cat - | cat -더 재미있게 만들기 위해 미리 추가해야합니까 ? 😉 나는 그것이 진짜 spandrel인지 확인하기 위해 테스트 한 후에 고칠 것이다
Connor

0

이것이 필요한 것이 정확히 확실하지 않으므로이 답변은 관련이 없을 수 있습니다. 항상 명령 출력을 저장할 수 있습니다.netstat >> output.txt , 나는 그것이 당신이 찾고있는 것이라고 생각하지 않습니다.

물론 프로그래밍 옵션이 있습니다. 해당 명령을 실행 한 후 위의 텍스트 파일을 읽도록 프로그램을 가져 와서 변수와 연관시킬 수 있습니다. 루비에서는 선택한 언어로 'backticks'를 사용하여 명령 출력에서 ​​변수를 만들 수 있습니다.

output = `ls`                       #(this is a comment) create variable out of command

if output.include? "Downloads"      #if statement to see if command includes 'Downloads' folder
print "there appears to be a folder named downloads in this directory."
else
print "there is no directory called downloads in this file."
end

이것을 .rb 파일에 넣고 실행 ruby file.rb하면 명령에서 변수가 만들어지고 조작 할 수 있습니다.


9
"아니 당신이이 필요한 것을 정확하게" 음, 말을하면 (하는 I 평균 I ) 단지, 오랜 기간 스크립트를 실행 한 출력을 검색하려면, 그리고 바보 실행하기 전에 출력을 리디렉션하는 것을 잊었다. 이제 스크립트를 다시 실행하지 않고 내 어리 석음을 해결하려고합니다.
jscs

0

즉시 구현할 시간이 없다는 아이디어가 있습니다.

그러나 다음과 같은 작업을 수행하면 어떻게됩니까?

$ MY_HISTORY_FILE = `get_temp_filename`
$ MY_HISTORY_FILE=$MY_HISTORY_FILE bash -i 2>&1 | tee $MY_HISTORY_FILE
$ some_command
$ cat $MY_HISTORY_FILE
$ # ^You'll want to filter that down in practice!

IO 버퍼링에 문제가있을 수 있습니다. 또한 파일이 너무 커질 수 있습니다. 이러한 문제에 대한 해결책을 제시해야 할 것입니다.


0

스크립트 명령을 사용하면 도움이 될 것이라고 생각합니다. 같은 것

  1. 스크립트 -c bash -qf fifo_pid

  2. bash 기능을 사용하여 구문 분석 후 설정


0

이전 명령을 다시 계산하지 않으려면 현재 터미널 버퍼를 스캔하고 마지막 명령의 -supposed- 출력을 추측하여 클립 보드에 복사 한 다음 마지막으로 터미널에 입력하는 매크로를 작성할 수 있습니다.

단일 출력 라인을 반환하는 간단한 명령에 사용할 수 있습니다 (우분투 18.04에서 테스트 됨 gnome-terminal).

다음 도구를 설치 xdootool, xclip,ruby

에서 gnome-terminal로 이동 Preferences -> Shortcuts -> Select all하고로 설정 Ctrl+shift+a.

다음 루비 스크립트를 작성하십시오.

cat >${HOME}/parse.rb <<EOF
#!/usr/bin/ruby
stdin = STDIN.read
d = stdin.split(/\n/)
e = d.reverse
f = e.drop_while { |item| item == "" }
g = f.drop_while { |item| item.start_with? "${USER}@" }
h = g[0] 
print h
EOF

키보드 설정에서 다음 키보드 단축키를 추가하십시오.

bash -c '/bin/sleep 0.3 ; xdotool key ctrl+shift+a ; xdotool key ctrl+shift+c ; ( (xclip -out | ${HOME}/parse.rb ) > /tmp/clipboard ) ; (cat /tmp/clipboard | xclip -sel clip ) ; xdotool key ctrl+shift+v '

위의 지름길 :

  • 현재 터미널 버퍼를 클립 보드에 복사
  • 마지막 명령의 출력을 추출합니다 (한 줄만).
  • 현재 터미널에 입력
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.