ole*_*leq 4 bash quoting function arguments
我喜欢使用以下模式在文件中搜索:
grep --color=auto -iRnHr --include={*.js,*.html,} --exclude-dir={release,dev,} "span" .
Run Code Online (Sandbox Code Playgroud)
然而,我想把这个包装成一个像这样的 bash 命令:
findinfiles {*.js,*.html,} {release,dev,} "span" // syntax is just a guessing
Run Code Online (Sandbox Code Playgroud)
我无法解决将这些类型的大括号传递给 bash 函数并将它们与$1
,$2
等一起使用的问题。当我使用以下内容时:
function findinfiles() {
echo $1, $2, $3
}
Run Code Online (Sandbox Code Playgroud)
然后:
me@pc ~> findinfiles {*.js,*.html,} {release,dev,} "span"
*.js, *.html, release
Run Code Online (Sandbox Code Playgroud)
当然,将参数传递给 grep 不会以这种方式工作。似乎参数已编入索引但未正确分组。
谁能教我如何处理这些争论?
当您运行时findinfiles {*.js,*.html,} {release,dev,} "span"
,会发生以下情况:
findinfiles
, {*.js,*.html,}
{release,dev,}
span
。findinfiles
, *.js
, *.html
, release
, dev
, span
。*.js
和*.html
以匹配文件名的列表。如果没有文件名与任一模式匹配,则将其保留。findinfiles
,发现它是一个函数,并使用提供的参数执行该函数。您可以防止在函数调用时扩展大括号和通配符,但是大括号将按字面出现在参数中,这不是特别有用。
我建议更改函数调用的格式。而不是使用大括号,只使用逗号,并在函数内手动拆分逗号处的参数。
findinfiles () {
local patterns="$1" excludes="$2" pattern="$3"
shift 3
typeset -a cmd dirs
if [[ $# -eq 0 ]]; then dirs=(.); else dirs=("$@"); fi
cmd=(grep --color=auto -iRnHr)
local IFS=,
for x in $patterns; do
cmd+=("--include=$x")
done
for x in $excludes; do
cmd+=("--exclude-dir=$x")
done
"${cmd[@]}" "${dirs}"
}
Run Code Online (Sandbox Code Playgroud)
说明:
dirs
为额外参数列表。如果没有,请使用.
(current directory) 代替。设置IFS
为逗号。当脚本包含类似$patterns
及$excludes
以上的不带引号的变量扩展时,shell 执行以下操作:
IFS
. 默认情况下,IFS
包含空白字符(空格、制表符和换行符)。(为了避免这些扩展步骤,请在变量替换周围使用双引号,如patterns="$1"
上面脚本中的等等。)
该函数构建命令行以在数组变量中增量执行cmd
。最后,执行命令。
或者,您可以基于以下设置进行构建:
shopt -s extglob globstar
fif_excludes='release dev'
alias fif='grep --color=auto -inH $fif_excludes'
Run Code Online (Sandbox Code Playgroud)
运行命令,如
fif span **/*.@(js|html)
Run Code Online (Sandbox Code Playgroud)
说明:
shopt -s extglob
激活@(js|html)
通配符模式的形式,它匹配js
或html
。(此选项激活其他模式形式,详细信息请参见手册。)shopt -s globstar
激活**/
与任何深度的子目录匹配的模式(即它执行递归遍历)。fif_excludes
变量。