简体   繁体   English

bash:'map'函数参数?

[英]bash: 'map' function arguments?

What is the most elegant way to essentially 'map' a list of bash arguments through some transformation (such as concatenating each string) before forwarding the list onto some other command?在将列表转发到其他命令之前,通过某种转换(例如连接每个字符串)基本上“映射”bash参数列表的最优雅方法是什么? Using xargs comes to mind but I can't seem to conceptualize how to do this.想到使用xargs但我似乎无法概念化如何做到这一点。

function do_something {
    # hypothetically
    for arg in "$@"; do
        arg="$arg.txt"
    done

    command "$@"
}

do_something file1 file2 file3

Such that the result would be to call command file1.txt file2.txt file3.txt .这样结果将是调用command file1.txt file2.txt file3.txt

What you've done is mostly correct, except that you'll need to use an array to store the new arguments:你所做的大部分是正确的,除了你需要使用一个数组来存储新参数:

function do_something {
    array=()
    for arg in "$@"; do
        array+=("$arg.txt")
    done

    command "${array[@]}"
}

do_something file1 file2 file3

You can use the following definition for a map that is similar to the one found in many functional programming languages (eg python , haskell ):您可以将以下定义用于与许多函数式编程语言(例如pythonhaskell )中的map类似的映射:

function map
{
    local f="$1"
    shift # consume first argument
    for arg
    do
        "$f" "$arg" # assuming `f` prints a single line per call
    done
}

Here's how you would use it in your example.这是您在示例中使用它的方式。 Here some_cmd may be a function defined locally:这里some_cmd可能是本地定义的函数:

function do_something
{
    local IFS=$'\n' # only split on newlines when word splitting
    result=($(map suffix "$@")) # split into lines and store into array
    some_cmd "${result[@]}" # call some_cmd with mapped arguments.
}
function suffix
{
    echo "$@".txt
}

do_something file1 file2 file3

Here's another variation of writing do_something .这是另一种写法do_something Here some_cmd must exist in $PATH :这里some_cmd必须存在于$PATH中:

function do_something
{
    map suffix "$@" | xargs some_cmd # call some_cmd with mapped arguments. 
}

The main downside is that to use the result in another function, you need to mess around with IFS to split on the newlines, or pipe into xargs;主要缺点是要在另一个函数中使用结果,您需要弄乱IFS以在换行符上拆分,或者通过管道输入 xargs; and if your map outputs contain newlines then either method fails completely.如果您的地图输出包含换行符,那么任何一种方法都会完全失败。

In order to "forward" arguments to other commands, there are several ways.为了将参数“转发”到其他命令,有几种方法。 Try this script:试试这个脚本:

printargs() {
  echo "Args for $1:"
  shift
  for a in "$@"; do
   echo "    arg: -$a-"
  done
}

printargs dolstar $*
printargs dolstarquot "$*"
printargs dolat $@
printargs dolatquot "$@"

and invoke it with test aguments:并使用测试参数调用它:

./sc.sh 1 2 3 ./sc.sh 1 2 3
Args for dolstar: dolstar 的参数:
arg: -1-参数:-1-
arg: -2-参数:-2-
arg: -3-参数:-3-
Args for dolstarquot: dolstarquot 的参数:
arg: -1 2 3-参数:-1 2 3-
Args for dolat: dolat 的参数:
arg: -1-参数:-1-
arg: -2-参数:-2-
arg: -3-参数:-3-
Args for dolatquot: dolatquot 的参数:
arg: -1-参数:-1-
arg: -2-参数:-2-
arg: -3-参数:-3-

Things go a little differently if an argument contains spaces:如果参数包含空格,情况会有所不同:

./sc.sh 1 "2 3" ./sc.sh 1 "2 3"
Args for dolstar: dolstar 的参数:
arg: -1-参数:-1-
arg: -2-参数:-2-
arg: -3-参数:-3-
Args for dolstarquot: dolstarquot 的参数:
arg: -1 2 3-参数:-1 2 3-
Args for dolat: dolat 的参数:
arg: -1-参数:-1-
arg: -2-参数:-2-
arg: -3-参数:-3-
Args for dolatquot: dolatquot 的参数:
arg: -1-参数:-1-
arg: -2 3-参数:-2 3-

The dolatquot "$@" is the only version that correctly forwards arguments. dolatquot "$@" 是唯一正确转发参数的版本。 Otherwise, as seen in another answer, you can manipulate arguments and construct a new list via arrays or a single string.否则,如另一个答案所示,您可以操纵参数并通过数组或单个字符串构造一个新列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM