【问题标题】:Concatenating remaining arguments beyond the first N in bash连接bash中第一个N之外的剩余参数
【发布时间】:2016-09-22 11:00:31
【问题描述】:

我以前不必编写任何 bash 脚本。这是我需要做的。

我的脚本将使用一组字符串参数运行。刺的数量将超过 8 个。我将必须连接字符串 9 及以后的字符串,并从中创建一个字符串。像这样……

myscript s1 s2 s3 s4 s5 s6 s7 s8 s9 s10....(完全未知)

在脚本中,我需要这样做...

新字符串 = s9 + s10 + ...

我正在尝试这样的事情......(来自网络搜索)。

 array="${@}"
 tLen=${#array[@]}
 # use for loop  to read string beyond 9
 for (( i=8; i<${tLen}; i++ ));
 do
   echo ${array[$i]}  --> just to show string beyond 9
 done

不工作。如果 i = 0,它会打印出来。这是我的意见。

./tatest 1 2 3 4 5 6 7 8 A B C

我希望打印 A B C。最后,我将不得不制作 ABC。

谁能帮忙?

【问题讨论】:

  • array="$@"array=${@} 实际上都没有创建数组; array 在这两种情况下都是一个字符串。如果您希望您的 array 实际上成为一个数组,它必须是 array=( "$@" )

标签: string bash loops


【解决方案1】:

应该比问题中的循环简单很多:

shift 8
echo "$*"

失去论点 1-8;将所有其他参数打印为单个字符串,并使用单个空格分隔参数(并保留参数中的空格)。

或者,如果你需要它在一个变量中,那么:

nine_onwards="$*"

或者如果你不能丢弃主 shell 进程中的前 8 个参数:

nine_onwards="$(shift 8; echo "$*")"

你可以检查至少有 9 个参数,当然,如果没有就抱怨。或者你可以接受一个空字符串——没有错误。

如果参数必须连接且没有空格(如对问题的修正),那么您必须使用$IFS

nine_onwards="$(shift 8; IFS=""; echo "$*")"

如果我正确地解释了这个答案下方的 cmets,那么您希望将前 8 个参数保存在 8 个单独的简单(非数组)变量中,然后将参数 9 往前保存在另一个简单变量中,两者之间没有空格参数值。

这很简单:

var1="$1"
var2="$2"
var3="$3"
var4="$4"
var5="$5"
var6="$6"
var7="$7"
var8="$8"
var9="$(shift 8; IFS=""; echo "$*")"

名称不必像它们那样密切相关。你可以使用:

teflon="$1"
absinthe="$2"
astronomy="$3"
lobster="$4"
darkest_peru="$5"
mp="$6"
culinary="$7"
dogma="$8"
concatenation="$(shift 8; IFS=""; echo "$*")"

您也不必按此顺序执行它们;任何序列(排列)都会很好。

还要注意,在问题中,您有:

array="${@}"

尽管有名称,但它创建了一个包含参数的简单变量。要创建一个数组,您必须像这样使用括号,其中空格是可选的:

array=( "$@" )

【讨论】:

  • 谢谢。我还需要将前 8 个变量保存在变量中。 9 及更高版本需要保存在另一个变量中。
  • 请更新您的问题(再次)以显示您真正追求的内容。没有什么比试图回答“不是我真正想问的问题”更令人沮丧的了。你说'变量'。你的意思是数组,正如你的问题所暗示的那样?分配array="$@" 没有做你认为它做的事情;它必须是array=( "$@" ),这些空格是可选的。
  • 很抱歉给您带来了困惑。我需要保存 8 个变量中的前 8 个。 9th 和以后应该连接在一起并保存在一个新变量中。
  • 你说的8个变量是指var1="$1"; var2="$2"; …; var8="$8"吗?或者将 8 个值分配给数组的元素就足够了?
  • var1="$1"; var2="$2"; ……; var8="$8"
【解决方案2】:
# Create a 0-index-based copy of the array of input arguments.
# (You could, however, work with the 1-based pseudo array $@ directly.)
array=( "${@}" )

# Print a concatenation of all input arguments starting with the 9th
# (starting at 0-based index 8), which are passed *individually* to
# `printf`, due to use of `@` to reference the array [slice]
# `%s` as the `printf` format then joins the elements with no separator 
# (and no trailing \n).
printf '%s' "${array[@]:8}"

# Alternative: Print the elements separated with a space:
# Note that using `*` instead of `@` causes the array [slice] to be expanded
# to a *single* string using the first char. in `$IFS` as the separator,
# which is a space by default; here you could add a trailing \n by using
# '%s\n' as the `printf` format string.
printf '%s' "${array[*]:8}"

注意array="${@}"创建一个数组 - 它只是创建一个字符串标量,包括输入数组元素的串联(总是),每个元素由 空格 分隔;要创建一个数组,您必须将它包含在(...) 中。

要根据您在follow-up question 中的要求,从第 9 个用双引号括起来 开始的参数创建一个以空格分隔的单个字符串,请使用以下命令:

printf -v var10 '"%s"' "${array[*]:8}"

您的问题$var10 的最后一个示例调用将包含文字"A B C"包括双引号。


至于将参数 1 到 8 分配给单个变量。:

Jonathan Leffler's helpful answer 展示了如何将前 8 个参数保存在单个变量中。

这是一个算法替代方案,它根据给定的名称前缀和序列号创建单个变量:

n=8  # how many arguments to assign to individual variables

# Create n 'var<i>' variables capturing the first n arguments.
i=0  # variable sequence number
for val in "${array[@]:0:n}"; do
  declare "var$((++i))=$val" # create $var<i>, starting with index 1
done

# Print the variables created and their values, using variable indirection.
printf "\nvar<i> variables:\n"
for varName in "${!var@}"; do
  printf '%s\n' "$varName=${!varName}"
done

【讨论】:

  • 如果你想将${array[@]:8}中的每个元素连接起来,并在元素之间添加一个空格,你需要做什么?
  • @Tas:请查看我的更新,这也解决了您的后续问题。
【解决方案3】:

你很接近 - 这样的事情会起作用:

array=( ${*} )
# use for loop  to read string beyond 9
for (( i=8; i<${#array[*]}; i++ ));
do
   echo -n ${array[$i]}
done

【讨论】:

  • 使用"$@" 代替未引用的${*}。如果脚本以./testest A 'B C' ' D E F ' G H I J K 0 1 2 或类似名称调用,则会有很大的不同。
  • 例如 ./testest A 'BC' ' DEF ' GHIJK 0 1 2, Using array=( ${*}) I get IJK012 using array="$*" 我什么也没得到,所以我仍然坚持我给出的答案,而不是你的评论不起作用!
  • 除非你的意思是 array=( "$@" )
  • 当然,我的意思是在array=( "$@" )(在修订版中)的上下文中,${*} 这四个字符应该替换为"$@"——老实说,我不知道怎么办我最初的评论可以解释。请注意,带有引号的命令行的输出应该是012;字母 I、J、K 是参数 6-8。您可以使用echo $6$7$8 进行验证。
猜你喜欢
  • 2012-06-24
  • 1970-01-01
  • 2012-02-21
  • 2014-10-19
  • 2019-07-07
  • 1970-01-01
  • 2016-12-09
  • 2021-11-15
  • 1970-01-01
相关资源
最近更新 更多