在Shell脚本中评估字符串


8

我正在遵循此bash shell脚本指南:

在“数字比较”部分中,引用了一个示例:

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

上面发生的事情是,我们在bash变量中存储了一串命令,然后在该变量上调用echo。似乎发生的事情是对字符串求值并执行wc命令并将行数返回到控制终端。

好的,所以我在Ubuntu 12.04中启动终端并尝试类似的操作:

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

请稍等片刻,这没有评估字符串并返回行数。那只是将字符串回送给终端。为什么我得到不同的结果?


注意NUM从未分配的字符串wc -l work.txt,而不是它的分配数量201
伊格尼斯

Answers:


2

您需要使用反引号来评估表达式。

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

如果只想在输出中看到“ 1”,请使用以下命令

$ num=`cat sample.txt | wc -l`
$ echo $num
1

并且也可以:

$ num=`wc -l < sample.txt`
$ echo $num
1

有关更多信息,请参见命令行上双引号“”,单引号''和反引号´´之间的区别?


知道为什么我会得到“ 1 sample.txt”而不是数字“ 1”吗?
JohnMerlino 2014年

这就是wc命令的工作方式。尝试cat sample.txt | wc -l
Danatela 2014年

wc -l显示文件中存在的行数及其文件名。
Avinash Raj

5

请注意该符号:

'

单引号

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

`

反引号

   Command substitution allows the output of a command to replace the com
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

因此,反引号会将命令的结果返回到标准输出。这就是为什么

`wc -l sample.txt`

返回命令的结果,而

'wc -l sample.txt'

只需像往常一样返回“ wc -l sample.txt”

考虑这样做:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

现在,回显所有三个变量:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts

4

如果要在变量中捕获命令的输出,则需要使用反引号``或将命令包含在以下命令中$()

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

请注意,实际上是在变量声明时(而不是在您回显它时)对字符串进行求值。该命令实际上在$()或反引号内运行,并且该命令的输出保存为变量的值。

通常,您应该始终使用$()而不是不推荐使用的反引号,并且仅出于兼容性原因而使用反引号,并且限制更多。例如,您不能在反引号内嵌套命令,但可以使用$()

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

有关应避免原因的更多详细信息,请参见U&L上的该主题``


1
我同意脚本应该更喜欢$( )` `。但是正如瓦格所说,反引号确实会嵌套。echo $(date -d $(echo yesterday))成为echo `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday)))成为echo `echo \`date -d \\\`echo yesterday\\\`\``。我说这不是反驳您的论点,而是要加强论点:转义的内部反引号使` `语法比通常认可的语法更强大,但是对的特殊处理却很\奇怪,令人惊讶且难以推理。随着$( )你所看到的通常是你会得到什么。
伊莱亚·卡根
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.