我正在尝试编写一个unix shell脚本来搜索给定文本的所有头文件,然后查找每个头文件包含在其他文件中的次数。
我的问题在第二部分,搜索其他文件中包含的命令在命令行中起作用,但它不会从shell脚本中打印任何内容。
array=( $(grep 'regexToSearch' -rl --include="*.h" pathToFiles) )
for item in "${array[@]}"
do
filename=$(echo ${item} | grep -o '[^/]*.h')
incstring="#include[ ]*\"$filename\""
echo $incstring
echo "--------------------"
filelist=$(grep '$incstring' -rl --include=*.{h,cpp} pathToFiles)
echo $filelist
echo "--------------------"
done
输出如下:
#include[ ]*"header1.h"
--------------------
// Second grep output for first file should be here
--------------------
#include[ ]*"header2.h"
--------------------
// Second grep output for second file should be here
--------------------
#include[ ]*"header3.h"
--------------------
// Second grep output for third file should be here
--------------------
答案 0 :(得分:0)
您在此命令中使用单引号:
filelist=$(grep '$incstring' -rl --include=*.{h,cpp} pathToFiles)
单引号禁止变量扩展。也就是说,您正在寻找文字字符串$incstring
而不是该变量的内容。此命令如此处所示,也不会在命令行上运行。
来自bash(1)
手册页:
用单引号括起字符可保留引号中每个字符的字面值。单身 引号可能不会出现在单引号之间,即使前面有反斜杠。
用双引号替换单引号:
filelist=$(grep "$incstring" -rl --include=*.{h,cpp} pathToFiles)
答案 1 :(得分:0)
首先,您构建数组的方式并不健全 - 如果您的头文件包含来自IFS
的字符,通配符等,则会导致一些相当令人惊讶的失败。
pathToFiles=.
# form the headers array in a manner robust against all possible filenames
headers=()
while IFS='' read -r -d '' filename; do
headers+=( "${filename#${pathToFiles}/}" )
done < <(grep -e "$regexToSearch" -Z -rl --include='*.h' "$pathToFiles")
for header in "${headers[@]}"; do
echo "--- ${header}"
# instead of capturing content, emit it directly to stdout
grep -F -e '#include "'"$header"'"' -rl --include='*.h' --include='*.cpp' "$pathToFiles"
echo "---"
done
此处给出的版本不允许#include
字符串和文件名之间有多个空格;这是为了支持grep -F
,它将字符串视为文字而非正则表达式,从而避免了文件名将不需要的表达式注入内容的潜在极端情况。