[英]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 ):您可以将以下定义用于与许多函数式编程语言(例如python 、 haskell )中的
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.