Bash命令的输出存储在任何寄存器中吗?例如,类似于$?捕获输出而不是退出状态。

我可以将输出赋值给一个变量:

output=$(command)

但那更多的是打字……


当前回答

仅用于非交互式命令的演示:http://asciinema.org/a/395092

为了也支持交互式命令,您必须从util-linux中修改脚本二进制以忽略任何屏幕重画控制台代码,并从bashrc运行它以将登录会话的输出保存到一个文件中。

其他回答

可以使用-exec命令在命令的输出信息上执行命令。所以这将是一个输出的重用作为一个例子给出了下面的find命令:

find . -name anything.out -exec rm {} \;

你在这里说->找到一个名为anything的文件。在当前文件夹中,如果找到,删除它。如果没有找到,则将跳过-exec之后的剩余部分。

是啊,为什么每次都多打几行;同意了。 您可以通过管道将命令返回的结果重定向到输入,但不能将打印输出重定向到输入(1>&0),至少不能用于多行输出。 此外,你也不希望在每个文件中一遍又一遍地编写相同的函数。让我们试试别的方法。

一个简单的解决方法是使用printf函数将值存储在变量中。

printf -v myoutput "`cmd`"

printf -v var "`echo ok;
  echo fine;
  echo thankyou`"
echo "$var" # don't forget the backquotes and quotes in either command.

另一种可定制的通用解决方案(我自己使用),用于只运行一次所需的命令,并逐行在数组变量中获得命令的多行打印输出。

如果您不将文件导出到任何地方,而只打算在本地使用它,则可以让Terminal设置函数声明。您必须在~/中添加函数。Bashrc文件或~/。概要文件。第二种情况下,您需要从“编辑>首选项>yourProfile>命令”中启用“运行命令作为登录shell”。

创建一个简单的函数,比如:

get_prev() # preferably pass the commands in quotes. Single commands might still work without.
{
    # 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
    
    # option 3: (I actually used below)
    eval "$*" > /tmp/out # or simply "$*" > /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<&-
}

因此,我们在选项1中所做的是将整个命令打印到一个临时文件/tmp/exe中并运行它,并将输出保存到另一个文件/tmp/out中,然后逐行读取/tmp/out文件的内容到一个数组中。 选项2和选项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_prev函数中创建的arr变量甚至可以在主脚本中的函数外部访问:

#get previous command outputs in arr
for((i=0; i<${#arr[@]}; i++))
do
    echo ${arr[i]}
done
#if you're sure that your output won't have escape sequences you bother about, you may simply print the array
printf "${arr[*]}\n"

编辑:

I use the following code in my implementation:
get_prev()
{
    usage()
    {
        echo "Usage: alphabet [ -h | --help ]
        [ -s | --sep SEP ]
        [ -v | --var VAR ] \"command\""
    }
    
    ARGS=$(getopt -a -n alphabet -o hs:v: --long help,sep:,var: -- "$@")
    if [ $? -ne 0 ]; then usage; return 2; fi
    eval set -- $ARGS
    
    local var="arr"
    IFS=$(echo -en '\n\b')
    for arg in $*
    do
        case $arg in
            -h|--help)
                usage
                echo " -h, --help : opens this help"
                echo " -s, --sep  : specify the separator, newline by default"
                echo " -v, --var  : variable name to put result into, arr by default"
                echo "  command   : command to execute. Enclose in quotes if multiple lines or pipelines are used."
                shift
                return 0
                ;;
            -s|--sep)
                shift
                IFS=$(echo -en $1)
                shift
                ;;
            -v|--var)
                shift
                var=$1
                shift
                ;;
            -|--)
                shift
                ;;
            *)
                cmd=$option
                ;;
        esac
    done
    if [ ${#} -eq 0 ]; then usage; return 1; fi
    
    ERROR=$( { eval "$*" > /tmp/out; } 2>&1 )
    if [ $ERROR ]; then echo $ERROR; return 1; fi
    
    local a=()
    exec 3</tmp/out
    while read -u 3 -r line
    do
        a+=($line)
    done
    exec 3<&-
    
    eval $var=\(\${a[@]}\)
    print_arr $var # comment this to suppress output
}

print()
{
    eval echo \${$1[@]}
}

print_arr()
{
    eval printf "%s\\\n" "\${$1[@]}"
}

我一直在用它来打印多个/流水线/两个命令的空格分隔输出,作为行分隔:

get_prev -s " " -v myarr "cmd1 | cmd2; cmd3 | cmd4"

例如:

get_prev -s ' ' -v myarr whereis python # or "whereis python"
# can also be achieved (in this case) by
whereis python | tr ' ' '\n'

现在tr命令在其他地方也很有用,比如

echo $PATH | tr ':' '\n'

但是对于多个/管道命令…你现在知道了。:)

himanshu

如果你不想重新计算前一个命令,你可以创建一个宏,它扫描当前终端缓冲区,尝试猜测最后一个命令的-假设-输出,将其复制到剪贴板,最后将其输入到终端。

它可以用于返回单行输出的简单命令(在Ubuntu 18.04上使用gnome-terminal进行测试)。

安装以下工具:xdootool、xclip、ruby

在gnome-terminal选择首选项->快捷方式->全选并设置为Ctrl+shift+a。

创建以下ruby脚本:

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键ctrl+shift+a;Xdotool键ctrl+shift+c;(xclip out | ${HOME}/parse. out)Rb) > /tmp/clipboard);(cat /tmp/clipboard | xclip -sel clip);Xdotool键ctrl+shift+v '

以上快捷方式:

将当前终端缓冲区复制到剪贴板 提取最后一个命令的输出(只有一行) 将其输入到当前终端

仅用于非交互式命令的演示:http://asciinema.org/a/395092

为了也支持交互式命令,您必须从util-linux中修改脚本二进制以忽略任何屏幕重画控制台代码,并从bashrc运行它以将登录会话的输出保存到一个文件中。

非常简单的解决方案

我已经用了很多年了。

脚本(添加到您的.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

我倾向于在所有命令的末尾添加|。这样,当我发现我想对一个缓慢运行的命令的输出进行文本处理时,我总是可以用ret检索它。