使用 xargs 将数组作为环境变量存储到非交互式 shell

使用 xargs 将数组作为环境变量存储到非交互式 shell

这是继续将数组存储为非交互式 shell 的环境变量 - 智库101 - 一个基于CC版权的问答分享平台善行难陀,让我问另一个问题。


我想找到包含特定正则表达式匹配的所有 Markdown 文件,然后按升序对文件(包含最多搜索词)的输出进行排序。

GREP(){
export Regex
xargs -0 -I "{}" bash -c 'grep "${GrepOption[@]}" --only-matching --with-filename --extended-regexp --regexp="${Regex}" "${1}" 2> /dev/null | wc -l | xargs printf "${1}:%s\n" ' _ "{}" \;
}

find . -name "*.md" -print0 | GREP | grep -v ':0$' | sort -n -r -k2 -t:

用户输入“${Regex}”。这里 GrepOptions 是取决于用户输入的选项数组。例如,GrepOptions 可以是GrepOptions=("--ignore-case")grep 选项的一些其他数组。

但我无法让该数组GrepOptions在子 shell 环境中可用。

有什么建议么?

答案1

问题是您想GrepOptions在代码中使用数组作为环境变量。你不能这样做,因为数组无法导出。

相反,您必须将选项bash -c以及要运行的路径名传递到脚本中grep

下面,我更进一步,还传递了正则表达式和多个找到的路径名,并且我是从-execinfind而不是使用xargs.

--在脚本的调用中使用bash -c来分隔路径名中的用户选项。

find . -name '*.md' -type f -exec bash -c '
    re=$1; shift
    while [[ $1 != "--" ]]; do
        opts+=( "$1" )
        shift
    done; shift

    for pathname do
        printf "%s:" "$pathname"
        grep -o -E -e "$re" "${opts[@]}" -- "$pathname" |
        wc -l | tr -d "[:blank:]"
    done | grep -v ":0$"' bash "$user_regex" "${user_options[@]}" -- {} + |
sort -t : -k2,2n

.md这将查找当前目录或以下目录中所有文件名后缀为 的常规文件。对于成批的此类文件,bash将执行一个脚本,该脚本采用用户提供的扩展正则表达式 ( $user_regex)、一些用户提供的命令选项grep$user_options,一个数组)以及一批路径名。

内联脚本挑选正则表达式和用户选项,然后继续循环找到的文件,grep在每个文件上运行并计算返回的行数。

每个文件的路径名都会在末尾的一个字符之后输出该数字:

表明没有匹配项的输出被淘汰,并对总体结果进行排序。

由于此代码处理路径名的方式,它不支持包含换行符或冒号的路径名。该user_options数组也不能包含单独的双破折号。

答案2

bash -c 'grep ${grepOptions+$grepOptions}  ....'
  • grepOptions 是一个 shell 变量,包含 grep 的选项,空格分隔。
  • 赤裸裸地使用 ${var+alternative} ;如果选项非空,则使用它们,否则使用 e 空的不带引号的,这会在解析中溶解
  • 这意味着 shell 变量是可导出的。

相关内容