ehi*_*ime 4 shell-script bashrc bash-scripting
我有一个用来查找东西的函数,但不幸的是,每当我向它传递一个控制字符($intVal或其他testing :)时,它就会窒息。我想知道修复是什么?
我可以理解在 grep中使用$or%或:etc 而不转义会导致此问题,但是由于我是通过引用传入的,因此我不确定如何转义它...
无论如何,这是代码。
function ffind()
{
if [ $1 ] ; then
find -type f | grep -ir '$1' * | grep -v '.svn'
else
echo "'$1' is not a valid resource"
fi
}
Run Code Online (Sandbox Code Playgroud)
例子):
$ ffind $intVal
'' is not a valid resource
$ ffind "testing :"
bash: [: testing: unary operator expected
'testing :' is not a valid resource
Run Code Online (Sandbox Code Playgroud)
$ ffind $intVal
'' is not a valid resource
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为这$foo是 variables 的语法,并且您没有名为intValset的变量,因此$intVal被转换为空字符串。由于该变量也未加引号,因此根本没有参数传递给ffind。
要解决此问题,请转义$– \$intVal(反斜杠)或'$intVal'(单引号)。
但是,如果您确实有一个名为 的变量intVal,请将其放在双引号中 – "$intVal"– 这将扩展变量的值,但不会拆分它。
请注意,bash 中没有“通过引用传递”这样的东西。只有按值传递和(棘手的)按名称传递。
$ ffind "testing :"
bash: [: testing: unary operator expected
'testing :' is not a valid resource
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为你忘了引号$1的if [ $1 ]线,因此它是受词分裂,和三个参数传递给[内置:
[”testing”:”]”而不是预期的两个:
[”testing :”]”示例 #1 也受此影响,因为[ $1 ]拆分为 (" [", " ]") 而不是 (" [", " ?", " ]")。示例 #1 是偶然工作的,因为显然[ ]是有效的。(我不知道……)
要解决此问题,请在$1–周围加上双引号[ "$1" ]。
注意:虽然[是标准的,但也有一个特定于 bash 的[[运算符,它实际上具有与其余代码不同的解析规则——特别是,它不拆分扩展变量。在 bash 中,[[ $1 ]]和[[ "$1" ]]两者都是等价的,不像它们的[替代品。
您的函数还存在示例中未显示的其他几个问题。
find -type f | grep -ir '$1' * | grep -v '.svn'
Run Code Online (Sandbox Code Playgroud)
在这一行:
这个词'$1'周围有单引号。这意味着bash不会扩展其内容——您实际上是在告诉grep搜索 regex $1,而不是命令行参数。
要解决此问题,请改用双引号 – "$1"
第一个grep命令被告知递归搜索当前目录(和通配符)中所有文件的内容。-r*
同时,您正在将 的输出通过管道传输find -type f到grep 中——似乎试图告诉grep搜索所有文件的名称。
这是行不通的,因为grep与大多数过滤器一样,如果给定一个或多个文件进行搜索,则不会从 stdin 读取。我不知道你要搜索什么——文件名或文件内容——所以选择一个:
要仅搜索文件名,请保留管道但删除文件规范:
find -type f | grep -i "$1" | ...
Run Code Online (Sandbox Code Playgroud)要仅搜索文件内容,请删除find|:
grep -ir "$1" * | ...
Run Code Online (Sandbox Code Playgroud)它是可以通过明确地给出这两个结合起来,grep的的“标准输入”文件:
find -type f | grep -i "$1" - * | ...
find -type f | grep -i "$1" /dev/stdin * | ...
Run Code Online (Sandbox Code Playgroud)
(/dev/stdin适用于所有 Linux 程序,而这-是一些程序使用的约定,包括 grep。)
在第二个grep命令中,搜索正则表达式有点太宽泛了。(请记住,它是一个正则表达式,而不是一个固定字符串。).svn甚至会匹配“ not-a-svn-file”之类的东西。
要排除.svn目录,请grep -v "/\.svn/"改用。
如果搜索文件内容( grep -ir ...),最好grep -v完全去掉该命令,并添加--exclude-dir=".svn"到第一个。
下面的项目只是sh脚本中的好习惯。
该function关键字是不必要的:ffind() { ...是足够的,而在所有POSIX弹作品(而function ffind 不会)。
如果脚本、程序或函数失败,它应该向其父级返回“失败”状态。按照惯例,Unix 程序认为0意味着“成功”和其他任何“失败”(尽管后者也有例外)。
要显式返回状态,请return <num>在函数(或exit <num>独立脚本)中使用:
else
echo "'$1' is not a valid resource" >&2
return 1
fi
Run Code Online (Sandbox Code Playgroud)类似地,错误消息不应与普通的 stdout 混合,而应使用重定向运算符写入stderr (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
}
Run Code Online (Sandbox Code Playgroud)
ack声称“比 grep 好”。运行ack "testing :"会搜索你的源代码,并自动跳过.svn和类似的目录。