在bash中的函数中设置位置参数

Posted

技术标签:

【中文标题】在bash中的函数中设置位置参数【英文标题】:setting a positional parameter in a function in bash 【发布时间】:2017-05-04 02:18:45 【问题描述】:

我正在制作一个函数,可以根据需要轻松地将我的字符串转换为数组。

我有点遇到一个奇怪的问题。我还是 bash 的新手,这真的让我很烦。有人能对此有所了解吗?

convert.sh

#!/bin/bash
convert2array () 
read -a $1_arr <<< $1


mx=$(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//')

convert2array "$mx"

echo $mx_arr[@]

输出:

bash -x convert2array.sh 
++ sed 's/\.$//'
++ cut '-d ' -f 2
++ dig +short google.com mx
+ mx='alt2.aspmx.l.google.com
alt3.aspmx.l.google.com
alt1.aspmx.l.google.com
aspmx.l.google.com
alt4.aspmx.l.google.com'
+ convert2array mx
+ read -a mx_arr
+ echo 585911
585911

【问题讨论】:

【参考方案1】:

如果数组只是一次性的,对于只读输出循环,POSIX shell可以做到:

set -- `dig +short google.com mx` ; \
while [ "$2" ] ; do echo "$2%.*" ; shift 2 ; done

输出:

alt2.aspmx.l.google.com
alt3.aspmx.l.google.com
alt4.aspmx.l.google.com
alt1.aspmx.l.google.com
aspmx.l.google.com

如果输出需要进一步处理,请将echo 传递给它需要做的任何其他事情。


注意:上面的代码包含一个简单的 kludge 来避免 sedcut -- 而是只输出 偶数 数组成员,并使用 parameter expansion "删除Smallest Suffix Pattern" 删除那个 '.'最后。

【讨论】:

【参考方案2】:

您可以直接将dig结果存储在数组中

 declare -a results=( $( dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//' ) )
 echo "$results[@]"

另外,你不需要在这里使用cut,单独使用sed就足够了。

declare -a results=( $( dig +short google.com mx  | sed -E 's/^[[:digit:]]*[[:blank:]]*(.*)\.$/\1/') )
echo "$results[@]"
aspmx.l.google.com
alt1.aspmx.l.google.com
alt2.aspmx.l.google.com
alt4.aspmx.l.google.com
alt3.aspmx.l.google.com

请参阅[ bash arrays ]、[ command subsctitution ] 和 [ positional parameters ]。

警告您:输出只能是一种格式。尽管( $( .. ) )comment#1 中指出的反模式,但对于这种情况,它就足够了。

【讨论】:

通过双引号替换命令,您总是会创建一个包含 所有行single 元素的数组,这不是本意。如果没有双引号,输出行总是会受到分词和通配符的影响,即使这恰好在 this 情况下起作用,( $(...) ) 也不是将命令输出读入的一般稳健方式一个数组(除非您设置 $IFS 并关闭通配符,这不值得)。 @mklement0 :感谢您的指点。我想了想,但后来忘了把双引号去掉,急着发表答案:) 现在改了 @mklement0 : 另外,我同意你评论的第二部分 我很高兴听到这个消息,但我真的希望您在解决方案前加上一个明显的警告。我认为( $(...) ) 是一种不应该推广的反模式。它非常简单,但它会回来咬你——见mywiki.wooledge.org/… @mklement0 : 说得好,让我想起了Bourne shell 中的阴暗角落,人们都在使用它们——Chet Ramey【参考方案3】:

尝试以下方法:

convert2array () 
  # Bash v4+ alternative: `readarray -t` instead of `IFS=$'\n' read -d '' -ra`
  IFS=$'\n' read -d '' -ra "$1" <<<"$2"


mx=$(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//')

convert2array mx_arr "$mx"

printf '%s\n' "$mx_arr[@]"

至于你尝试了什么:

convert2array 中的$1 不是输入变量$mx名称,而是它的。 您需要将要显式声明的变量的名称(可能在修改输入名称之后)作为单独的参数传入。

read 默认情况下只读取输入的 第一 行,而您传递 多个 行。-d '' 使 @ 987654327@ 读取所有行,IFS=$'\n' 使read读取每一行。 在 Bash v4+ 中,使用内置的readarrayIFS=$'\n' read -d '' -ra 可以替换为readarray -t


命令的简化版本是使用 Bash v4+ readarray 内置函数将 dig ... 输出行直接读取到数组中:

readarray -t mx_arr < <(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//')

Bash v3.x 替代方案:

IFS=$'\n' read -d ''  -ra mx_arr < <(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//')

【讨论】:

【参考方案4】:

只是说明你的函数出了什么问题:

convert2array () 
read -a $1_arr <<< $1

在这里,当您想要读取变量本身的内容时,您正在读取$1 的内容,这是变量的名称。你可以在这里使用间接:

convert2array () 
  read -a $1_arr <<< $!1

正如其他人所指出的,有更简单的方法可以将您的输出保存在数组中。

【讨论】:

以上是关于在bash中的函数中设置位置参数的主要内容,如果未能解决你的问题,请参考以下文章

Bash中的位置参数和特殊参数

在 C++ 中的可变长度函数中放置默认值参数的位置?

如何使用 HUE 在 Impala 查询中设置变量?

R语言笔记 R中设置图形参数--函数par()详解

jQuery用x和y位置动画背景位置[重复]

怎样在hbuilder中设置图片路径