“查找-exec sh -c”中的Grep变量扩展

时间:2019-03-07 14:58:10

标签: linux bash grep pipe

我编写了一个脚本,该脚本在单词文档中循环以匹配其中的单词。下面是一个有效的示例,并找到数字43。其后是一个无效的脚本。我只想在脚本开始时将数字43作为变量,但是它似乎无法正确扩展。有什么想法可以在脚本中使用43作为变量而不是对其进行硬编码吗?

有效的脚本:

find . -type f -name '*.docx' -exec sh -c '
  for file do
docx2txt "$file" 2>/dev/null - | grep -i --color "43" && printf "\033[1;32mFound in ${file}\033[0m\n"
#readlink -f "$file"
  done
' sh {} +

无效的脚本:

scan_var=43
find . -type f -name '*.docx' -exec sh -c '
  for file do
docx2txt "$file" 2>/dev/null - | grep -i --color "$scan_var" && printf "\033[1;32mFound in ${file}\033[0m\n"
#readlink -f "$file"
  done
' sh {} +

3 个答案:

答案 0 :(得分:3)

从安全角度来看,您应该使用export通过环境将变量公开给子进程,而不是将这些变量替换为解析为代码的字符串(这样容易导致shell injection攻击)。

也就是说:

export scan_var=43  ## the **only** change is to this line!

# only modifications to code below are formatting with no functional impact
# ...well, and safer printf use (to not expand format strings in filenames)
find . -type f -name '*.docx' -exec sh -c '
  for file do
    docx2txt "$file" 2>/dev/null - \
    | grep -i --color "$scan_var" \
    && printf "\033[1;32mFound in %s\033[0m\n" "$file"
  done
' sh {} +

答案 1 :(得分:2)

sh -c派生一个子进程,该变量不可见,请参见Charles' answer以获取修复。

将变量放入-exec sh -c的另一种方法是将其用作参数。考虑

$ var=43
$ sh -c 'echo "$var"'         # Expands to nothing

$ sh -c 'echo "$1"' sh "$var"  # Gets variable value into sh -c
43

请注意,命令后sh -c的第一个参数在$0(进程名称)中用作sh -c

应用于您的命令:

scan_var=43
find . -type f -name '*.docx' -exec sh -c '
    scan_var=$1
    shift
    for file do
        echo docx2txt "$file" 2>/dev/null - \
            | grep -i --color "$scan_var" \
            && printf "\033[1;32mFound in ${file}\033[0m\n"
        # readlink -f "$file"
    done
' sh "$scan_var" {} +

将第一个参数的值读入scan_var,然后用shift丢弃该参数。

答案 2 :(得分:0)

您将避免在单引号内使用变量。 调整grep命令行:

grep -i --color "'"$scan_var"'" && ...

这将关闭find -exec之前的$scan_var中的单引号,并为其余代码开始单引号。