如何从脚本外部提取脚本分配给环境变量的值?

如何从脚本外部提取脚本分配给环境变量的值?

我有两个 .sh 文件(比如test1.shtest2.sh)。

test1.sh包含:

export OMP_NUM_THREADS=8

test2.sh包含:

export OMP_NUM_THREADS=4

这两个文件还包含许多其他 shell 命令。

现在我正在创建另一个 .sh 文件,我想在其中找到OMP_NUM_THREADS上述两个 .sh 文件 ( test1.shandd test2.sh) 中使用的值。该怎么做?

答案1

您可以使用单个grep命令来实现这一点。

这将提取N从类似行开始,每行打印一个,其中export OMP_NUM_THREADS=NN是一个或多个十进制数字的序列(0-9):

grep -hoP '^export OMP_NUM_THREADS=\K\d+' test1.sh test2.sh

这将打印:

8
4

注意事项

你可能会注意到这有点类似于wjandrea 的方式. 与该解决方案类似,只要满足以下条件,此方法即可奏效:

  • 您知道这些文件被称为test1.shtest2.sh(或它们的实际名称),因此您可以在命令中列出文件名。
  • 您不必担心每个文件可能存在多个匹配项,或者您想要全部匹配项。
  • 即使没有空格,也可以忽略最后一位数字右侧的文本。这可能不是问题;假设您对这些脚本有一定的控制权(或您信任的人有),并且他们不会将非数字值赋予OMP_NUM_THREADS。但是,一个合理的替代方案是使用\bafter\d+来确保匹配出现在词边界(如果没有则不会产生结果)。

就像任何无法执行的解决方案一样非常复杂的分析(这是只是有时可能),假设:

  • 真的正在寻找特定的文本;您不需要实际解析脚本并弄清楚它在运行时的行为。如果您的目标是找出OMP_NUM_THREADS脚本导出到其环境中的值,这可能会或可能不会实现。这取决于脚本的编写方式。特别是,仅仅因为脚本中出现了与模式匹配的行并不能确保该行被执行。包含它的脚本可以退出首先,它可以被控制ifcase, 或者while/until;它甚至可以是更大命令的一部分或评论如果前一行以。。结束\(这不是一份详尽的清单。)
  • 还要注意,如果一个变量被导出,那么稍后被分配没有内置export函数,新值也会成为导出值。export导出变量并可选地为其赋值,但实际上它们是分开的——当您更改值时,这将应用于导出的变量。同样,脚本可以在导出变量后从环境中删除它们。(参见这篇文章由 Nathan Long 撰写了解详情。

命令行选项的作用-hoP

  • -h标志阻止grep打印文件名;如果没有它,您将得到:

    test1.sh:8
    test2.sh:4
    
  • -o标志仅打印匹配的文本;如果没有它,您将获得整行:

    export OMP_NUM_THREADS=8
    export OMP_NUM_THREADS=4
    
  • -P标志使用Perl 兼容正则表达式(PCRE)。我使用这个正则表达式方言,因为它支持\K(见下文)。

该模式每个部分的^export OMP_NUM_THREADS=\K\d+作用:

在第三个脚本中分别提取两个值。

您提到您计划编写使用这些值的第三个脚本。根据您目前所问的问题,如何最好地做到这一点无法完全回答。但是,通常希望将单独的值捕获到单独的 shell 变量中。

您可以从中提取值test1.sh到 shell 变量中n1,并将从中提取值test2.sh到 shell 变量中,n2如下所示:

#!/bin/sh

get_num_threads() {
    grep -oP '^export OMP_NUM_THREADS=\K\d+' "$1"
}

n1="$(get_num_threads test1.sh)"
n2="$(get_num_threads test2.sh)"

这使用命令替换获得grep原本的输出写入标准输出. 无需编写grep两次命令或引入第二步来处理它是输出,我把它放在shell 函数. 该函数被调用两次来分配n1n2"$1" 扩展为 test1.sh在第一次通话和test2.sh第二次通话中。

您可以在上面显示的代码之后放置任何您想要脚本运行的代码,该代码使用存储在n1和中的值。n2

  • 我省略了该-h标志,因为在此脚本中,get_num_threadsshell 函数(您可以调用它)几乎任何你喜欢的) 每次仅用于处理一个文件。-h不过,如果您愿意,也可以保留。
  • 如果你希望脚本以不同于外壳sh,更改#!/bin/sh 哈希班线因此。如果你只是计划脚本 ( ),您可以将其完全删除;请记住,除非您随后取消定义它们,否则. scriptname脚本将获得get_num_threadsn1和定义的任何 shell 源。n2
  • 按照编写的脚本,如果或中存在多个匹配行,则脚本会很乐意为n1或分配多个数字。如果这不是您想要的,那么您必须相应地修改脚本。n2test1.shtest2.sh

为了说明同一文件中多个匹配行的当前行为,请考虑如果附加以下内容会发生什么情况printf命令脚本会打印每个匹配项,并用[ ]空行包围并分隔:

printf '[%s]\n\n' "$n1" "$n2"

假设test1.sh有一场匹配(8)并且test2.sh有两场匹配(4 和 5)。然后你会得到:

[8]

[4
5]

这就是说,n2包含 4 和 5,中间用新队,就像grep输出它们一样。

答案2

grep -oP '(?<=^export OMP_NUM_THREADS=)[0-9]+' test1.sh test2.sh

解释

  • grep -o仅打印行的匹配部分
  • grep -P使用与 Perl 兼容的正则表达式
  • (?<=...)不视为...匹配的一部分。这是正向后视。
  • ^在此上下文中,表示行的开始
  • [0-9]+匹配一个或多个数字

答案3

如果两者都在同一个文件夹中,名为find

grep -R  -i "OMP_NUM_THREADS=[0-9]*" find/ | cut -d':' -f2 | sed -e 's/[^0-9]*//g'

更简单的版本:

grep -R  -i "OMP_NUM_THREADS=[0-9]*" find/ | cut -d':' -f2 | cut -d'=' -f2

示例文件:

test1.sh --> export OMP_NUM_THREADS=8, export OMP_NUM_THREADS=20
test2.sh --> export OMP_NUM_THREADS=8

输出:

8
20
8

解释:

  1. grep递归地遍历包含目标文件的文件夹,并找到OMP_NUM_THREADS在字符末尾带有一组数字的条目=

  2. grep将其结果传递给 cut,根据:(由引入grep)将它们分开并取第二个字段值。

  3. cut然后传递给另一个cut命令或sed命令。如果cut给出结果,它会重复前一个cut命令所做的事情,但这次会根据=字符分离值。如果传递给sed它,它会搜索并删除非数字并返回结果。

相关内容