首页 > 解决方案 > 未使用 .bash_profile 中定义的 xargs 调用函数

问题描述

我在 .bash_profile 中添加了以下两个函数

function dc(){
    local command="docker container $@"
    echo $command
    eval $command
}

function dcp(){
    local params=$@
    local result=""
    for attr in $params
    do
        result=$result"{{.$attr}}\t"
    done

    local params="--format \"table $result\""

    echo "$params"
}

现在请在采购 .bash_profile 后找到以下执行:-

~ $

dc ls
docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
bb1bb407f422        busybox             "sh"                2 hours ago         Up 2 hours                              foo
6b0bfe6d8615        busybox             "sh"                2 hours ago         Up 2 hours                              baz

~ $

dcp Image ID
--format "table {{.Image}}\t{{.ID}}\t"

~ $

dcp Image ID | xargs docker container ls
IMAGE               CONTAINER ID
busybox             bb1bb407f422
busybox             6b0bfe6d8615

~ $

dcp Image ID | xargs dc ls
dc: unrecognized option `--format'
Usage: dc [OPTION] [file ...]
  -e, --expression=EXPR    evaluate expression
  -f, --file=FILE          evaluate contents of file
  -h, --help               display this help and exit
  -V, --version            output version information and exit

Email bug reports to:  bug-dc@gnu.org .

现在,xargs dc ls并没有覆盖到xargs docker container ls

如何告诉 xargs 扩展dc ls调用


编辑1:-

按照建议,我更新.bash_profile中的代码,如下所示:-

dcCall(){
    echo "params are : >$@<"
    local command=( docker images "$@" )
    echo ${command[*]}
    ${command[@]}
}

export -f dcCall
alias dc="xargs bash -c 'dcCall "$@"'"


dcp(){
    local params=$@
    local result=""
    for attr in $params
    do
        result=$result"{{.$attr}}\t"
    done

    local params="--format \"table $result\""

    echo "$params"
}

现在,dc 被声明为别名,因此可以像这样使用它:-

dcp Repository ID | dc

但是执行上述命令会产生以下结果:-

~ $

dcp Repository ID | dc
params are : ><
docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
clouderassh                    latest              93f38a6c0288        34 hours ago        6.81GB
busybox                        latest              d8233ab899d4        8 days ago          1.2MB
microsoft/mssql-server-linux   2017-CU8            229d30f7b467        8 months ago        1.43GB
cloudera/quickstart            latest              4239cd2958c6        2 years ago         6.34GB

现在,dcp 存储库 ID的参数没有传递给 dc ,并且dcCall函数中的参数为空。

标签: bashfunctionexpand

解决方案


  1. 您不需要同时使用“function”关键字和括号。
  2. 我正在尝试将命令放入变量中,但复杂的情况总是失败!
  3. 忘记在 bash/POSIX shell 中引用变量的安全隐患

使用数组来存储命令,那么你不需要eval

dc() {
    local command=( docker container "$@" )
    echo "${command[*]}"   # print it
    "${command[@]}"        # execute it
}

并通过 xargs 访问您的函数:

dcp Image ID | xargs bash -XXX 'dc "$@"' _ ls
  1. 如果将 dc 函数放在 ~/.profile 或 ~/.bash_profile 中,则 -XXX 为-lc
  2. 如果你把 dc 函数放在你的 ~/.bashrc 中,那么 -XXX 是-ic
  3. 如果你export -f dc,那么 -XXX 是-c

参考:https ://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files


您的“编辑 1”:

  • 在 dcCall 函数中缺少所需的双引号(如我上面的函数所示)
  • 别名是用双引号字符串定义的,因此定义别名时会扩展shell 变量。

别名不是答案。如果你想要dcp Repository ID | dc ls行为,那么

dc() {
    xargs docker container "$@"
}

从更大的角度来看,该dcp函数似乎专门为docker container ls命令生成参数,不是吗?如果是,那么我会将 xargs 管道折叠为一个函数:

dls() {
    local OPTIND OPTARG
    local params=()

    while getopts ':p:' opt; do
        case $opt in
            p) params+=( "{{.$OPTARG}}"$'\t' ) ;;
            ?) echo "unknown option: -$OPTARG" >&2 ;;
        esac
    done
    shift $((OPTIND - 1))

    local docker_params=()
    if (( ${#params[@]} != 0)); then 
        docker_params+=( --format "table ${params[*]}" )
    fi

    echo docker container ls "${docker_params[@]}" "$@"
}

你会像这样使用它

dls -p Image -p ID

推荐阅读