2017-04-13 161 views
2

我需要执行命令,我需要显示我执行了哪个命令。所以我一直在尝试将命令存储在变量中并执行该变量。在显示输出时,我正在打印如下的变量值。如何在执行命令之前回显命令行?

var="ls -ltr"; 
echo "$var \n `$var`"; 

上面一个是给输出我想要的,但是当我使用的是下面提及的命令,它扔我一个error.can有人建议我如何存储下文提到的命令。

var="ls -ltr|wc -l"; 
echo "$var \n `$var`"; 

输出错误:

ls -ltr | wc -l 
ls: cannot access |: No such file or directory 
ls: cannot access wc: No such file or directory 

什么是存储在可变命令类似下面的命令的正确方法。或者给我任何其他建议以满足我的要求。

cat passwd.txt|tr ' ' '\n'|egrep -i "$pwd_in"|sort 
+5

必备链接:http://mywiki.wooledge.org/BashFAQ/050 –

+1

真的**双重阅读**上述链接。在变量中存储命令几乎在所有情况下都是错误的想法...... – jm666

+0

@tripleee:这个问题是关于在执行它之前想要回应任意命令行。链接的问题是关于为什么由shell扩展引起的引号没有语法意义。虽然有一些关系,但它们不是重复的。 – mklement0

回答

0

以下是关于Bash的内容。试试这个:

var="ls -ltr|wc -l"; 
echo -e "$var \n `eval $var`"; 

Output: 
ls -ltr|wc -l 
10 
+0

你在$ var中存储了什么,以及如何? –

+0

你存储的是同样的东西。 –

+1

@SriramP它的工作原理是使用'eval'来评估字符串为命令行。 – JeremyP

3

把你的命令放在一个函数中并启用xtrace

cmd() 
{ 
    set -x 
    ls -ltr | wc -l 
    set +x 
} 
2

你的方法没有工作的原因是,shell元字符,如|失去了意义语法时,他们嵌入式this related question的答案解释了原因;该问题是关于嵌入报价,但答案仍适用类似。
另外,它是generally ill-advised to store commands in variables;总之:

  • 没有 - 不明智的 - 使用eval,它仅适用于简单命令(命令未与控制运营商的帮助下由多个命令,如|&&) ,
  • 然后只有在将命令的参数存储在数组中时才有效。

得到你想要的东西,周围有使用eval,这是generally discouraged for security reasons没有办法。

  • 简而言之:仅使用eval,如果你完全控制或信任你传递给eval串;也就是说,使用eval用,比如,可变$vareval "$var")是可以接受的,当且仅当
    • 完全控制分配给$var的价值,知道这是一个命令,并知道它的工作原理如果(即使部分的值由外部源提供,下一点适用)
    • 信任$var的任何外部贡献来源(无论其全部还是部分构成$var的值) - 具体而言,您需要确保不会尝试恶意提供/注入不需要的命令。

      注:

最可预测的eval基于解决方案如下,其提高了AxT_8041's answer(既bashksh作品)由于此命令是由您构建,作为文字,您完全控制命令字符串,所以eval是可以接受的在这种情况下是

cmdLine='ls -ltr|wc -l' 
printf "%s\n" "$cmdLine"; eval "$cmdLine" 

引用命令得到棘手更复杂的命令行,在这种情况下,你可以使用这里文档

# Read the command into variable $cmdLine. 
read -d '' -r cmdLine <<'EOF' 
cat passwd.txt|tr ' ' '\n'|egrep -i "$pwd_in"|sort 
EOF 
printf "%s\n" "$cmdLine"; eval "$cmdLine" 

注:虽然这个命令也由您构建,它是通过合并变量$pwd_in的值形成的,所以为了在这里安全地使用eval,您必须知道或信任$pwd_in具有期望种类的值,值得注意的是它不包含尝试注入命令


安全的,但有限的解决方案就是使用由壳提供的诊断功能:

bash的情况下,set -v自动被执行之前每个原始命令行回波(没有必要在一个可变第一定义感兴趣的命令):

set -v   # Turn echoing of raw command lines on. 
ls -ltr | wc -l # Execute the command of interest. 
set +v   # Turn back off. 

所这产生,例如:

ls -ltr | wc -l 
15 
set +v 

但是,也有限制:

  • 该猛砸回波被发送到stderr的原始命令行。

    • 注意set -xceving's answer是相关的功能,但它的工作方式不同:它会单独呼应简单命令(ls -ltrwc -l),使在他们的已经展开形式的管道。
  • set +v输出行不能被压制,从我所知道的。

你可以尝试解决这些问题,但它不会很容易或漂亮。