简体   繁体   English

如何在bash变量中使用linux命令

[英]How to use linux commands in bash variables

I am trying to create a bash script to perform the same action of the below command : 我正在尝试创建一个bash脚本来执行以下命令的相同操作:

dig -x 8.8.8.8 | grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5

Output is google-public-dns-a.google.com. 输出为google-public-dns-a.google.com.

Now I have created the script test.sh as below : 现在,我创建了脚本test.sh,如下所示:

#!/bin/bash
IP=$1
output1=$(dig -x $IP)
grepg="grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5"
go=$($output1 | $grepg)
echo $go

and called the script as ./test.sh 8.8.8.8. 并将脚本命名为./test.sh 8.8.8.8。 But getting errors. 但是会出错。 How can I store Linux commands inside bash variables effectively with quotes ? 如何使用引号有效地将Linux命令存储在bash变量中?
Thanks 谢谢

There are a couple of problems here. 这里有两个问题。

The first is that you're trying to execute as a command the contents of the variable $ouptut1 , which is just the dig output; 第一个是您要尝试将变量$ouptut1的内容作为命令执行,这只是dig输出。 it's not a command. 这不是命令。 You probably meant echo $output1 . 您可能是说echo $output1

Then you are trying to execute the contents of variable $grepg as a pipeline. 然后,您尝试将变量$grepg的内容作为管道执行。 But parsing a line into the components of a compound command (a pipeline is a compound command) happens before parameter expansion. 但是将一行解析为复合命令的组成部分(管道是复合命令)是在参数扩展之前进行的。 So if you execute something like this: 因此,如果执行以下操作:

foo="echo hello | grep hi"
$foo

This first gets broken apart into a single simple command, then the command is expanded, then it is parsed into arguments. 首先将其分解为单个简单命令,然后将该命令扩展,然后将其解析为参数。 So this is equivalent to running: 因此,这等效于运行:

echo hello "|" grep hi

In general, it's not a good idea to store strings of text that you want to have evaluated in variables. 通常,将要评估的文本字符串存储在变量中不是一个好主意。 There are a few very special cases in which you may want to do it, but in almost every case (and probably your case) there's a better way to do it. 在一些非常特殊的情况下,您可能想要这样做,但是在几乎每种情况下(可能还有您的情况下),都有一种更好的方法。 I'm going to warn you against it, but if you really want to evaluate a string as a command, you can use eval , for example: 我会警告您,但如果您真的想将字符串作为命令求值,则可以使用eval ,例如:

go=$(echo $output1 | eval $grepg)

What you seem to want is to define a shell function. 您似乎想要的是定义一个shell函数。 If you want to reuse that pipeline several times, running several different values through it, just define a shell function. 如果您想重复使用该管道几次,并通过它运行几个不同的值,则只需定义一个shell函数即可。 That function is a single command that acts as the equivalent of the contained commands: 该函数是一个命令,等效于所包含的命令:

function grepg() {
    grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5
}

go=$(echo $output1 | grepg)

To simplify your code further, you can avoid all of the intermediate variables. 为了进一步简化代码,可以避免使用所有中间变量。 If you're just going to pipe the results of the dig command into grepg , you don't need to save it in a variable before doing so. 如果只是要将dig命令的结果通过管道grepggrepg ,则无需在执行此操作之前将其保存在变量中。 And if you're just going to echo the results to stdout, again you don't need to store it in a variable, you can just let the output go to stdout: 而且,如果您只是将结果回显到stdout,则无需再次将其存储在变量中,只需将输出传递到stdout:

#!/bin/bash
IP=$1
function grepg() {
    grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5
}

dig -x $IP | grepg

I'm assuming here that you wanted to factor out the function so you could use it several times in your script; 我在这里假设您想分解该函数,以便可以在脚本中多次使用它。 if not, if you're just going to use it once, you could simplify further to: 如果不是,如果只使用一次,则可以进一步简化为:

#!/bin/bash
IP=$1
dig -x $IP | grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5

Note that if you want to store a pipeline like this in a variable so that you could use some other code to decide between two functions, and apply one or the other depending on some condition, I'd recommend defining the function like above, and then just storing the single function name in the variable. 请注意,如果要将这样的管道存储在变量中,以便可以使用其他代码来决定两个函数之间的关系,并根据某些条件应用一个或另一个,则建议您定义上述函数,并且然后只将单个函数名称存储在变量中。 That will work the way you expect: 这将按照您期望的方式工作:

function grepg() {
    grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5
}

function grepf() {
    # do something else, I'm not creative enough to come up with a good example
}

if [ "$2" = "foo" ]
then
    func=grepg
else
    func=grepf
fi

dig -x $IP | $func

为什么不简单地:

dig -x "$1" | grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5

output1 stores the results of dig -x $IP , not the command itself since you're using $( ) . output1存储dig -x $IP的结果,而不存储命令本身,因为您使用的是$( )

grepg stores the command as a string, which is fine but is giving you some unexpected results. grepg将命令存储为字符串,这很好,但是会给您一些意想不到的结果。

On this line: 在这行上:

go=$($output1 | $grepg) 

it tries to pipe the output from dig into a single program called "grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5" . 它尝试将dig的输出传递到一个名为"grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5"

What you probably want is: 您可能想要的是:

#!/bin/bash
IP=$1
output1="dig -x $IP"
grepg="grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5"
go=$(eval $output1 | eval $grepg)
echo $go

The dig command is stored as a string in output1 , just like grepg stores the other command. dig命令作为字符串存储在output1 ,就像grepg存储另一个命令一样。

Also, eval is needed here as well. 另外,这里也需要eval Without eval it thinks that the entire string is the program name, instead of a program name followed by arguments, pipes, etc. 如果不使用eval它将认为整个字符串是程序名称,而不是后跟参数,管道等的程序名称。

That means it's looking for a program called "grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5" rather than looking for grep followed by an argument, followed by a pipe, and so on. 这意味着它正在寻找一个名为"grep PTR | cut -d ' ' -f 2 | grep google | cut -f 5"而不是在grep后跟一个参数,一个管道,等等。

Your piped chain of commands can be shortened to a single awk command: 您的管道命令链可以缩短为单个awk命令:

dig -x 8.8.8.8 | awk '/PTR[[:space:]]/{print $NF}'
google-public-dns-a.google.com

I case you want to search for google also in the same line: 如果您也想在同一行中搜索google

dig -x 8.8.8.8| awk '/PTR[[:space:]]/ && /google/ {print $NF}'

To store its output in a bash variable, use: 要将其输出存储在bash变量中,请使用:

go=$(dig -x 8.8.8.8| awk '/PTR[[:space:]]/{print $NF}')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM