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

时间:2019-05-27 03:27:13

标签: bash

采用以下示例:

ls -l | grep -i readme | ./myscript.sh

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

这可能吗?

4 个答案:

答案 0 :(得分:3)

不,这不可能。

在操作系统级别,使用mkfifo()dup2()fork()execve()系统调用来实现管道。 这不能提供一种方法来告诉程序与其stdin连接的命令是什么。确实,不能保证成为代表正在使用的程序管道的字符串即使您的标准输入确实是连接到另一个程序的标准输出的FIFO,也完全不会生成标准输入;可能是管道是由直接调用execve()和朋友的程序生成的。

最好的解决方法是反转您的流程。

这不是您要的,但是您可以得到。

#!/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'。 (当然,除非作为示例,否则请不要使用它;请参见ParsingLs。)

答案 1 :(得分:2)

通常无法完成,但是在满足某些条件的情况下,使用history中的bash命令可以完成 项。

  • history必须打开。

  • myscript.sh 开始以来,只有一个shell正在运行或接受新命令(或失败,运行 myscript.sh )。

  • 由于默认情况下未将带有前导空格的命令行保存到历史记录中,因此 myscript.sh 的调用命令必须没有前导空格;或必须更改默认值-请参见Get bash history to remember only the commands run with space prefixed

  • 调用命令必须以&结尾,因为没有它,直到 myscript.sh 完成后,新的命令行才会被添加到历史记录中。

该脚本必须是bash脚本,(它不能与/bin/dash一起使用),并且调用外壳程序需要做一些准备工作。在脚本第一次运行之前的某个时间:

shopt -s histappend
PROMPT_COMMAND="history -a; history -n"

...这使bash的历史可遗传。 (代码从unutbu's answer to a related question刷入。)

然后 myscript.sh 可能会出现:

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

试运行:

echo googa | ./myscript.sh &

输出,(减去相关的“ &”部分):

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

通过将“ &”更改为“ & fg”,可以将任务数量减半,但是结果输出中将不包括后缀“ fg”。

答案 2 :(得分:0)

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

./myscript.sh "$(ls -l | grep -i readme)"

答案 3 :(得分:-1)

我认为有可能,看看这个例子:

#!/bin/bash
result=""
while read line; do
  result=$result"${line}"
done
echo $result

现在使用管道运行此脚本,例如:

ls -l /etc | ./script.sh

希望对您有所帮助:)