Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux bash使用特定分隔符分隔参数_Linux_Bash_Shell_Makefile_Gnu Make - Fatal编程技术网

Linux bash使用特定分隔符分隔参数

Linux bash使用特定分隔符分隔参数,linux,bash,shell,makefile,gnu-make,Linux,Bash,Shell,Makefile,Gnu Make,我正在搜索一个命令,该命令用一个特定的分隔符分隔所有给定的参数,并以引号将它们输出 示例(分隔符设置为冒号:): 应该输出 "this is":"a":"test" 我知道shell在将参数传递给命令之前会解释“”引号。因此,该命令实际上应该做的是打印出引号中的每个给定参数,并用冒号分隔所有这些参数 我也不是在寻找一个只有bash的解决方案,而是在寻找最优雅的解决方案。 在这些元素的数组上循环并这样做非常容易,但问题是我必须在gnu makefile中使用它,它只允许单行shell命令,并使

我正在搜索一个命令,该命令用一个特定的分隔符分隔所有给定的参数,并以引号将它们输出

示例(分隔符设置为冒号
):

应该输出

"this is":"a":"test"

我知道shell在将参数传递给命令之前会解释“”引号。因此,该命令实际上应该做的是打印出引号中的每个给定参数,并用冒号分隔所有这些参数

我也不是在寻找一个只有bash的解决方案,而是在寻找最优雅的解决方案。

在这些元素的数组上循环并这样做非常容易,但问题是我必须在
gnu makefile
中使用它,它只允许单行shell命令,并使用
sh
而不是
bash


因此,越简单越好。

如果阵列中已经有了它们,则可以使用此命令

MYARRAY=("this is" "a" "test")
joined_string=$(IFS=:; echo "$(MYARRAY[*])")
echo $joined_string
设置IFS(内部字段分隔符)将是字符分隔符。在阵列上使用echo将使用新设置的IFS显示阵列。将这些命令放入$()将把echo的输出放入连接的字符串。

怎么样

somecommand () {
    printf '"%s"\n' "$@" | paste -s -d :
}
使用
printf
添加引号并在单独的一行中打印每个条目,然后使用
paste
,使用
-s
(“序列”)选项和冒号作为分隔符

可以这样称呼:

$ somecommand "this is" "a" test
"this is":"a":"test"
用法示例:

$ apply_delimiter hello world "how are you"
"hello":"world":"how are you"

正如许多评论所指出的,一种简单的“循环”方法,即循环作为参数传递的每个字符串是一种相当直接的方法:

delimit_colon() {
    local first=1
    for i in "$@"; do
        if [ "$first" -eq 1 ]; then
            printf "%s" "$i"
            first=0
        else
            printf ":%s" "$i"
        fi
    done
    printf "\n"
}
当与一个简短的测试脚本相结合时,可以是:

#!/bin/bash

delimit_colon() {
    local first=1
    for i in "$@"; do
        if [ "$first" -eq 1 ]; then
            printf "%s" "$i"
            first=0
        else
            printf ":%s" "$i"
        fi
    done
    printf "\n"
}

[ -z "$1" ] && {  ## validate input
    printf "error: insufficient input\n"
    exit 1
}

delimit_colon "$@"

exit 0
测试输入/输出

$ bash delimitargs.sh "this is" "a" test
this is:a:test

这里是一个使用z-shell的解决方案:

#!/usr/bin/zsh
# this is "somecommand"
echo '"'${(j_":"_)@}'"'

“循环很容易”-那么为什么不这样做呢?因为在gnu makefile中,我只能有单行语句,而且它们只能在shell中执行,而不是在bash中执行。通过“引用输出”,引用的目标到底是什么?它是否旨在
eval
-安全报价?它应该如何处理数据中的文字引号字符?什么是正确的引用取决于什么软件将要解析给定的字符串,我不相信这个问题会说明这一点。顺便说一句,您确实意识到您可以从makefile控制哪个shell使用,对吗?非常非常清楚,这里所做的引用不安全(也不是简单地替换单引号)。如果参数中有
'$(rm-rf~)'
,则在求值时将以双引号发出;而
$'\'$(rm-rf~)\“
将是一个能够转义单引号的版本,等等。如果您想生成eval-safe-quoting,这是
printf%q
的作业(而生成有效的JSON-quoting是
jq
的作业,生成Python-safe-quoting是
Python-c'import sys;print repr(sys.argv[1])”的作业。
等等)。为了使这一点正确地适用于这个问题,我建议使用
$*
而不是
${MYARRAY[*]}
(因为它专门指的是参数)。此外,您可能需要引用扩展名作为
echo
.Hmm的参数。您几乎可以使用
printf':%s“
只修剪第一个字符,或者将
放在末尾,修剪最后一个字符。如果shell是bash而不是sh(默认情况下由makefiles使用),这样不仅可以避免管道,甚至可以避免子shell。这正是我想到的解决方案,谢谢。@CharlesDuffy这确实是可能的,因为生成的命令不关心尾随的命令。但是printf的这个功能叫什么?从来没有听说过。@bricklore,…如果有额外参数,支持重复格式字符串还有剩余的吗?我不确定它的名称是否较短。:)
$ bash delimitargs.sh "this is" "a" test
this is:a:test
#!/usr/bin/zsh
# this is "somecommand"
echo '"'${(j_":"_)@}'"'