Shell命令在shell中工作,但在shell脚本中不工作

时间:2013-08-02 13:16:51

标签: shell grep

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

2 个答案:

答案 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,它将字符串视为文字而非正则表达式,从而避免了文件名将不需要的表达式注入内容的潜在极端情况。