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_":"_)@}'"'