BASH 函数不转义控制字符

BASH 函数不转义控制字符

我有一个用来查找内容的函数,但不幸的是,每当我向其传递控制字符($intValtesting :等)时,它就会卡住。我想知道修复方法是什么?

我可以理解在 grep 中使用$%:而不进行转义会导致此问题,但由于我通过引用传递它,所以我不确定如何转义它......

无论如何,这是代码。

function ffind()
{
     if [ $1 ] ; then
         find -type f | grep -ir '$1' * | grep -v '.svn'
     else
         echo "'$1' is not a valid resource"
     fi
}

例子):

$ ffind $intVal
'' is not a valid resource

$ ffind "testing :"
bash: [: testing: unary operator expected
'testing :' is not a valid resource

答案1

第一个例子

$ ffind $intVal
'' is not a valid resource

这不起作用,因为$foo是变量的语法,并且您没有名为intValset 的变量,因此$intVal被转换为空字符串。由于变量也没有加引号,因此根本没有任何参数传递给ffind

要修复此问题,请转义$\$intVal(反斜杠)或'$intVal'(单引号)。

如果你真的一个名为的变量intVal,但是,把它放在双倍的改为引号 –"$intVal"– 这将扩大变量的值,但不会分割它。

请注意没有这样的事在 bash 中为“按引用传递”。只有按值传递和(棘手的)按名称传递。

第二个例子

$ ffind "testing :"
bash: [: testing: unary operator expected
'testing :' is not a valid resource

这不起作用,因为你忘了加引号$1在线上if [ $1 ],因此它是受分词影响,并且三个参数被传递给[内置函数:

  • [
  • testing
  • :
  • ]

而不是预期的两个:

  • [
  • testing :
  • ]

示例 #1 也受此影响,因为[ $1 ]它拆分为 (" [", " ]") 而不是 (" [", " ", " ]")。但是示例 #1 偶然成功,因为它显然[ ]是有效的。(我不知道……)

$1为了修复此问题,请在–周围加上双引号[ "$1" ]

笔记:虽然[是标准的,但也有一个特定于 bash 的[[运算符,它实际上具有与其余代码不同的解析规则 - 特别是,它不拆分扩展变量。在 bash 中,[[ $1 ]][[ "$1" ]]都是等效的,与它们的替代方案不同[

更多错误

您的函数还存在一些示例中未显示的其他问题。

find -type f | grep -ir '$1' * | grep -v '.svn'

在这一行中:

  1. 这个词'$1'用单引号括起来。这意味着狂欢不会扩展其内容——你实际上是在告诉grep搜索正则表达式$1,而不是命令行参数。

    要解决这个问题,请改用双引号 -"$1"

  2. 首先grep命令被告知要递归搜索内容当前目录中的所有文件(-r*通配符)。

    同时,你正在将输出传输find -type fgrep– 似乎想告诉grep搜索名称所有文件。

    这是行不通的,因为grep与大多数过滤器一样,如果给定一个或多个文件进行搜索,则不会从 stdin 读取。我不知道您要搜索什么——文件名或文件内容——所以选择一个:

    • 要仅搜索文件名,请保留管道但删除文件规范:

       find -type f | grep -i "$1" | ...
      
    • 要仅搜索文件内容,请删除find|

       grep -ir "$1" * | ...
      
    • 可以结合两者,通过明确给出grep“stdin”文件:

       find -type f | grep -i "$1" - * | ...
      
       find -type f | grep -i "$1" /dev/stdin * | ...
      

      /dev/stdin适用于所有 Linux 程序,而-是使用的约定一些程序,包括 grep。)

  3. 在第二grep命令,搜索正则表达式有点太宽泛。(请记住,这是一个正则表达式,而不是固定字符串。).svn甚至会匹配像“ not-a-svn-file”这样的内容。

    要排除.svn目录,请改用grep -v "/\.svn/"

    如果搜索文件内容grep -ir ...),最好完全删除该grep -v命令,并添加--exclude-dir=".svn"到第一个命令中。

你可以停止阅读

以下项目只是很好的练习脚本。

  1. 关键字function是不必要的:ffind() { ...足够了,并且在所有 POSIX shell 中都可以工作(而function ffind 不会)。

  2. 如果脚本、程序或函数失败,则应向其父级返回“失败”状态。按照惯例,Unix 程序认为0表示“成功”,其他情况则表示“失败”(尽管后者也有例外)。

    要明确返回状态,请return <num>在函数(或exit <num>独立脚本)中使用:

    else
        echo "'$1' is not a valid resource" >&2
        return 1
    fi
    
  3. 类似地,错误消息不应与正常标准输出混合,而应写入标准错误(fd #2),使用>&重定向运算符(参见上例)。这样,您可以将正常输出重定向到文件(例如ffind intVal > results.txt),同时仍将错误显示在屏幕上。

固定代码

ffind()
{
     if [ "$1" ] ; then
         grep -ir --exclude-dir=".svn" "$1" .
     else
         echo "'$1' is not a valid resource" >&2
         return 1
     fi
}

更好的工具

确认声称“比 grep 更好”。运行后ack "testing :"会搜索源代码,并自动跳过.svn和类似的目录。

相关内容