0

我正在尝试编写一个 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
--------------------
4

2 回答 2

0

首先,你形成数组的方式并不可靠——如果你的头文件包含一个字符 from 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,它将字符串视为文字而不是正则表达式,从而避免文件名将不需要的表达式注入内容的潜在极端情况。

于 2013-08-02T13:36:09.660 回答
0

您在此命令中使用单引号:

    filelist=$(grep '$incstring' -rl --include=*.{h,cpp} pathToFiles)

单引号禁止变量扩展。也就是说,您正在寻找文字字符串$incstring而不是该变量的内容。如此处所示,此命令也不会在命令行上运行。

bash(1)手册页:

将字符括在单引号中会保留引号内每个字符的字面值。单引号之间不能出现单引号,即使前面有反斜杠。

用双引号替换单引号:

    filelist=$(grep "$incstring" -rl --include=*.{h,cpp} pathToFiles)
于 2013-08-02T13:21:31.940 回答