我有两个 .sh 文件(比如test1.sh
和test2.sh
)。
test1.sh
包含:
export OMP_NUM_THREADS=8
test2.sh
包含:
export OMP_NUM_THREADS=4
这两个文件还包含许多其他 shell 命令。
现在我正在创建另一个 .sh 文件,我想在其中找到OMP_NUM_THREADS
上述两个 .sh 文件 ( test1.sh
andd test2.sh
) 中使用的值。该怎么做?
答案1
您可以使用单个grep
命令来实现这一点。
这将提取N
从类似行开始,每行打印一个,其中export OMP_NUM_THREADS=N
N
是一个或多个十进制数字的序列(0-9):
grep -hoP '^export OMP_NUM_THREADS=\K\d+' test1.sh test2.sh
这将打印:
8
4
注意事项
你可能会注意到这有点类似于wjandrea 的方式. 与该解决方案类似,只要满足以下条件,此方法即可奏效:
- 您知道这些文件被称为
test1.sh
和test2.sh
(或它们的实际名称),因此您可以在命令中列出文件名。 - 您不必担心每个文件可能存在多个匹配项,或者您想要全部匹配项。
- 即使没有空格,也可以忽略最后一位数字右侧的文本。这可能不是问题;假设您对这些脚本有一定的控制权(或您信任的人有),并且他们不会将非数字值赋予
OMP_NUM_THREADS
。但是,一个合理的替代方案是使用\b
after\d+
来确保匹配出现在词边界(如果没有则不会产生结果)。
就像任何无法执行的解决方案一样非常复杂的分析(这是只是有时可能),假设:
- 你真的正在寻找特定的文本;您不需要实际解析脚本并弄清楚它在运行时的行为。如果您的目标是找出
OMP_NUM_THREADS
脚本导出到其环境中的值,这可能会或可能不会实现。这取决于脚本的编写方式。特别是,仅仅因为脚本中出现了与模式匹配的行并不能确保该行被执行。包含它的脚本可以退出首先,它可以被控制if
,case
, 或者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+
作用:
^
火柴行首export
。如果您希望它能够出现在该行的任何位置,请将其删除。export OMP_NUM_THREADS=
与本身从字面上理解相匹配。\K
丢弃迄今为止已匹配的文本,这样它就不会出现在比赛中。\d+
火柴任意十进制数字(\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 函数. 该函数被调用两次来分配n1
和n2
;"$1"
扩展为 test1.sh
在第一次通话和test2.sh
第二次通话中。
您可以在上面显示的代码之后放置任何您想要脚本运行的代码,该代码使用存储在n1
和中的值。n2
- 我省略了该
-h
标志,因为在此脚本中,get_num_threads
shell 函数(您可以调用它)几乎任何你喜欢的) 每次仅用于处理一个文件。-h
不过,如果您愿意,也可以保留。 - 如果你希望脚本以不同于外壳
sh
,更改#!/bin/sh
哈希班线因此。如果你只是计划源脚本 ( ),您可以将其完全删除;请记住,除非您随后取消定义它们,否则. scriptname
脚本将获得get_num_threads
、n1
和定义的任何 shell 源。n2
- 按照编写的脚本,如果或中存在多个匹配行,则脚本会很乐意为
n1
或分配多个数字。如果这不是您想要的,那么您必须相应地修改脚本。n2
test1.sh
test2.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
解释:
grep
递归地遍历包含目标文件的文件夹,并找到OMP_NUM_THREADS
在字符末尾带有一组数字的条目=
。grep
将其结果传递给 cut,根据:
(由引入grep
)将它们分开并取第二个字段值。cut
然后传递给另一个cut
命令或sed
命令。如果cut
给出结果,它会重复前一个cut
命令所做的事情,但这次会根据=
字符分离值。如果传递给sed
它,它会搜索并删除非数字并返回结果。