将命令结果存储在变量更改结果中

时间:2021-01-18 02:50:37

标签: bash

我正在尝试使用 grep 执行多行正则表达式,以从 javascript 文件中查找和删除某些 ESLint 注释(我不认为它是 javascript 的事实非常相关,只是提供上下文)。

this question 的帮助下我学会了使用 -Pzo 来使用 Perl regex,在每个匹配的末尾放置空字符而不是换行符(基本上将整个文件视为一行),并且只输出匹配的部分。这些选项一起为我提供了以下命令: grep -Pzo '(?s)\s*\/\* globals .*?\*\/' "file.js"

当我从终端运行这个命令时,我得到了我期望的输出。例如:


/* globals text text */
/* globals text text */
/* globals text text */
/* globals text text */
/* globals text */
/* globals text */
/* globals text */
/* globals text */
/* globals text */
/* globals ...
        ... */

我想在 bash 脚本中运行这个命令并将结果存储在一个数组中。从 this question 我学会了如何从命令输出创建一个数组,我想出了这个脚本:

#!/bin/bash
matches=( $(grep -Pzo '(?s)\s*\/\* globals .*?\*\/' "file.js") )
for m in "${matches[@]}"; do
    echo "${m}"
done

但是当我运行这个脚本时,echo 的输出看起来像这样:

/bin
/boot
/dev
/etc
/home
/init
... more directories, then it repeats
/bin
...

grep 在终端中的运行方式与我缺少的脚本之间是否存在一些细微差别?从我的终端和脚本报告中运行 bash --version

GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

1 个答案:

答案 0 :(得分:2)

是这一行:

matches=( $(grep -Pzo '(?s)\s*\/\* globals .*?\*\/' "file.js") )

因为命令替换的输出没有加引号,shell 将应用分词和文件名扩展(阅读 Security implications of forgetting to quote a variable in bash/POSIX shells 了解所有详细信息)。

显然 /**/ 将扩展为一堆文件。

要将命令的输出行读入数组,请使用 mapfile 和从进程替换重定向的输入:

mapfile -t matches < <(grep ...)
相关问题