Bash获取正在传输到脚本中的命令

Bash获取正在传输到脚本中的命令,bash,Bash,以以下为例: ls -l | grep -i readme | ./myscript.sh 我要做的是在myscript.sh中获取ls-l | grep-I自述作为字符串变量。因此,本质上,我试图在myscript.sh中使用的最后一个管道之前获取整个命令 这可能吗 我认为应该像这样将其作为一个字符串参数传递 ./myscript.sh "$(ls -l | grep -i readme)" 不,不可能。 在操作系统级别,管道是通过mkfifo、dup2、fork和execve系统调用实现

以以下为例:

ls -l | grep -i readme | ./myscript.sh
我要做的是在myscript.sh中获取ls-l | grep-I自述作为字符串变量。因此,本质上,我试图在myscript.sh中使用的最后一个管道之前获取整个命令


这可能吗

我认为应该像这样将其作为一个字符串参数传递

./myscript.sh "$(ls -l | grep -i readme)"
不,不可能。 在操作系统级别,管道是通过mkfifo、dup2、fork和execve系统调用实现的。这并没有提供一种方法来告诉程序连接到其stdin的命令是什么。事实上,即使您的stdin实际上是连接到另一个程序stdout的FIFO,也不能保证有一个字符串表示用于生成stdin的程序管道;这可能是管道是由程序直接调用execve和friends生成的

最好的解决方法是颠倒流程。 这不是你想要的,而是你能得到的

#!/usr/bin/env bash
printf -v cmd_str '%q ' "$@"  # generate a shell command representing our arguments

while IFS= read -r line; do
  printf 'Output from %s: %s\n' "$cmd_str" "$line"
done < <("$@")       # actually run those arguments as a command, and read from it
…然后让脚本启动它从中读取输入的内容,而不是在stdin上接收它们


…之后,./yourscript ls-l,或./yourscript sh-c'ls-l | grep-i readme'。当然,除非作为一个例子,否则不要使用它;请参阅。

通常无法执行此操作,但如果满足某些条件,使用bash中的history命令可以执行此操作:

历史必须开启

自myscript.sh启动以来,只有一个shell在运行,或接受新命令,或运行myscript.sh失败

由于默认情况下,带有前导空格的命令行不会保存到历史记录中,因此myscript.sh的调用命令必须没有前导空格;或者必须更改默认值-请参阅

调用命令需要以&结尾,因为没有它,新的命令行在myscript.sh完成之前不会添加到历史记录中

脚本必须是bash脚本,不能与/bin/dash一起使用,调用shell需要做一些准备工作。在运行脚本之前,请先执行以下操作:

shopt -s histappend
PROMPT_COMMAND="history -a; history -n"
…这使得狂欢节的历史可以传承。代码从中删除

那么myscript.sh可能会:

#!/bin/bash
history -w
printf 'calling command was: %s\n' \
    "$(history | rev | 
       grep "$0" ~/.bash_history | tail -1)"
试运行:

echo googa | ./myscript.sh &
输出,减去相关的积垢(&C):

calling command was: echo googa | ./myscript.sh &

通过更改&to&fg可以将积垢减半,但结果输出将不包括fg后缀。

我认为这是可能的,请看以下示例:

#!/bin/bash
result=""
while read line; do
  result=$result"${line}"
done
echo $result
现在使用管道运行此脚本,例如:

ls -l /etc | ./script.sh

我希望这会对您有所帮助:

不,这是不可能的。你得到的只是先进先出;你没有办法知道它的另一面是什么。而且,这已经被问到了;请给我一分钟时间尝试查找重复项…作为一种更好地说明是否可以合理预期它是否可能的方法,请记住,关于管道的任何内容都不是特定于Shell的,或者根本不需要输入命令行。如果你有一个C程序,它的mkfifos、dup2和execves的集合与shell建立管道的集合相同,那么你将有相同的程序集合以相同的方式连接,但是没有一个字符串描述它曾经被构造过;单字符串结构是shell内部的,被调用的程序从未见过。@vintnes,将其输出存储在文件中如何为处理该文件的程序提供创建该文件的命令文本?因为这就是他们在这里要求的——能够访问创建他们输入的命令的文本。@CharlesDuffy XY问题,那么。没有人会处于这种境地。谢谢。但这不是我想要实现的。命令的输出将通过管道传输到myscript.sh,因此我需要在opc中保留语法。您是否尝试了我共享的内容?$命令将展开表达式,并将命令的输出转换为字符串。我想这正是你想要的achieve@HernanGarcia,OP不是要求命令的输出,而是要求实际的命令本身。他们已经有了可以通过阅读stdin获得的输出。这太棒了!但是,我实际上已经使用getopt实现了参数化选项。我想看看我是否能做的是颠倒顺序。这是我的完整脚本。您会注意到,在第99行中,todo是我尝试在我的命令变量中为post请求捕获管道输出的地方。当我尝试跟踪它时,该链接显示为不可用…也就是说,如果您只是尝试捕获管道内容,content=$cat是将所有stdin读入单个变量所需的全部内容,这确实是一个XY问题。不,我认为你最初的评估是正确的。我试图捕获正在通过管道传输到脚本的命令,而不是正在通过管道传输的命令的输出。为了获得输出,我使用read。这是整个脚本的新链接。注:第99BTW行,
PaSTBIN充满了JavaCRIPT-Y,动画广告。请考虑使用类似或向前的东西。该示例演示了如何访问脚本LS-L/ETC,而不是命令的输出?BTW,您应该总是引用扩展;echo$result,而不是echo$result;否则,如果一个名称包含一个*并且周围有空格,f/e,它将被一个附加名称的列表替换。这显然是非常脆弱的。如果您同时运行多个shell,您需要希望您足够幸运,在正确的时间刷新了正确的shell的历史记录。您还需要希望该命令的调用方式不会阻止它以某些选项显示在历史记录中,f/e,在空格前加前缀可以做到这一点,并且用户没有取消设置HISTFILE,这是我在运行不值得保存的内容时经常做的事。@charlesduff,谢谢。见修改后的答案。在历史被刷新时,它似乎无论如何都会这样做,但也许用历史来引导脚本-w不会伤害…点头。尽管我警告说这不是人们应该尝试实际做的实践,但这是一个有效的答案,有大量但充分披露的警告,在这里有它是一个有用的补充。