我正在尝试使用 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>
答案 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 ...)