如何将命令的输出分配给shell变量?


76

我想将表达式的结果分配给变量并将其与字符串连接,然后回显它。这是我得到的:

#!/bin/bash
cd ~/Desktop;
thefile= ls -t -U | grep -m 1 "Screen Shot";
echo "Most recent screenshot is: "$thefile;

但是输出:

Screen Shot 2011-07-03 at 1.55.43 PM.png
Most recent screenshot is: 

因此,它似乎没有分配给$thefile,而是在执行时被打印。


Answers:


108

外壳分配是一个单词,等号后没有空格。因此,您编写的内容为分配了一个空值thefile;此外,由于分配是与命令组合在一起的,因此它会生成thefile一个环境变量,并且该分配对于该特定命令而言是本地的,即仅通过调用即可ls看到分配的值。

您要捕获命令的输出,因此需要使用命令替换

thefile=$(ls -t -U | grep -m 1 "Screen Shot")

(一些文献显示了另一种语法thefile=`ls …`;反引号语法等效于美元括号语法,除了有时反引号内的引用很奇怪,因此只需使用即可$(…)。)

有关脚本的其他说明:

  • -t(按时间排序)与-U(不排序)结合起来是没有道理的;只是使用-t
  • 与其grep用于匹配屏幕截图,不如将通配符传递给ls并用于head捕获第一个文件,这一点更加清晰:

    thefile=$(ls -t *"Screen Shot"* | head -n 1)
  • 解析输出ls通常是一个坏主意。如果文件名带有不可打印的字符,则可能会严重失败。但是,ls如果没有,则很难按日期对文件进行排序,因此,如果您知道文件名中没有不可打印的字符或反斜杠,那么这是一个可以接受的解决方案。

  • 始终在变量替换周围使用双引号,即在这里写

    echo "Most recent screenshot is: $thefile"

    如果不使用双引号,则变量的值将重新扩展,如果它包含空格或其他特殊字符,则会引起麻烦。

  • 您不需要在行尾使用分号。它们是多余的但无害。
  • 在Shell脚本中,通常包含一个是一个好主意set -e。这告诉外壳程序如果任何命令失败(通过返回非零状态)则退出。

如果您有GNU查找(特别是在运行非嵌入式Linux或Cygwin的情况下),则还有另一种查找最新文件的方法:find列出文件及其日期,并使用sorttail提取最年轻的文件。

thefile=$(find -maxdepth 1 -type f -name "*Screen Shot*" -printf "%T@ %p" |
          sort -k 1n | tail -n 1)

如果您愿意用zsh而不是bash编写此脚本,则有一种捕获最新文件的简便方法,因为zsh具有glob限定符,不仅可以在名称上而且可以在文件元数据上进行通配符匹配。在(om[1])该模式之后的部分是水珠限定符; om根据年龄的增加对比赛进行排序(即按照修改时间,最新的优先),并[1]仅提取第一个比赛。整个匹配项都需要放在括号中,因为从技术上讲,它是一个数组,因为遍历会返回文件列表,即使这[1]意味着在这种特殊情况下该列表最多包含一个文件。

#!/bin/zsh
set -e
cd ~/Desktop
thefile=(*"Screen Shot"*(om[1]))
echo "Most recent screenshot is: $thefile"

7
哇!比我可能希望的更多的信息。多次感谢您的答复;我非常感谢您为此付出的一切努力!您刚刚向我展示了我确实有很多东西要学。我打算去买一本书:P。
内森·G。

3
这就是我所说的明确答案!:)
Alex

4

如果要使用多行/多行命令执行此操作,则可以执行以下操作:

output=$( bash <<EOF
#multiline/multiple command/s
EOF
)

要么:

output=$(
#multiline/multiple command/s
)

例:

#!/bin/bash
output="$( bash <<EOF
echo first
echo second
echo third
EOF
)"
echo "$output"

输出:

first
second
third

这是一个很好的答案。有没有一种方法可以在命令中指定变量?例如output=$(echo $someVariable)
Zach Smith
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.