Arrays 将Bash数组转换为分隔字符串

Arrays 将Bash数组转换为分隔字符串,arrays,string,bash,delimited-text,Arrays,String,Bash,Delimited Text,我想知道以下几点: 为什么给定的非工作示例不起作用 除了工作示例中给出的方法外,是否还有其他更干净的方法 非工作示例 工作示例 在上下文中,命令中用于进一步分析的分隔字符串 # REVISION: 2017-03-14 # Use of read and other bash specific features (bashisms) 因为括号用于分隔数组,而不是字符串: ids="1 2 3 4";echo ${ids// /|} 1|2|3|4 一些示例:使用两个字符串填充$id:ab和c

我想知道以下几点:

  • 为什么给定的非工作示例不起作用
  • 除了工作示例中给出的方法外,是否还有其他更干净的方法
  • 非工作示例

    工作示例

    在上下文中,命令中用于进一步分析的分隔字符串

    # REVISION: 2017-03-14
    # Use of read and other bash specific features (bashisms)
    
    因为括号用于分隔数组,而不是字符串:

    ids="1 2 3 4";echo ${ids// /|}
    1|2|3|4
    
    一些示例:使用两个字符串填充
    $id
    ab
    cd

    ids=("a b" "c d")
    
    echo ${ids[*]// /|}
    a|b c|d
    
    IFS='|';echo "${ids[*]}";IFS=$' \t\n'
    a b|c d
    
    。。。最后:

    IFS='|';echo "${ids[*]// /|}";IFS=$' \t\n'
    a|b|c|d
    
    其中数组是组合的,由
    $IFS
    的第一个字符分隔,但在数组的每个元素中用
    |
    替换空格

    当您这样做时:

    id="${ids[@]}"
    
    通过空格将数组
    ids
    的合并生成的字符串转换为字符串类型的新变量

    注意:
    “${ids[@]}”
    给出一个空格分隔的字符串时,
    “${ids[*]}”
    (用星号
    *
    代替at符号
    @
    )将呈现一个由
    $IFS
    第一个字符分隔的字符串

    man bash说了什么:

    man -Len -Pcol\ -b bash | sed -ne '/^ *IFS /{N;N;p;q}'
       IFS    The  Internal  Field  Separator  that  is used for word splitting
              after expansion and to split  lines  into  words  with  the  read
              builtin command.  The default value is ``<space><tab><newline>''.
    

    字面上是一个
    空格
    ,一个
    制表
    和一个
    换行
    。所以,第一个字符是一个空格。使用
    *
    @
    的作用相同

    但是

    {
    


    IFS=:read-a array<您的第一个问题已在中解决。下面是连接数组元素的标准方法:

    ids=( 1 2 3 4 )
    IFS=\| eval 'lst="${ids[*]}"'
    

    有些人会大声喊出,
    eval
    是邪恶的,但由于单引号,它在这里是完全安全的。这样做的唯一好处是:没有子shell,
    IFS
    没有全局修改,它不会修剪尾随的换行符,而且非常简单。

    您也可以使用
    printf
    ,无需任何外部命令或操作IFS:

    ids=(1 2 3 4)                     # create array
    printf -v ids_d '|%s' "${ids[@]}" # yields "|1|2|3|4"
    ids_d=${ids_d:1}                  # remove the leading '|'
    

    将参数数组连接到分隔字符串的实用函数:

    #/usr/bin/env bash
    #用分隔符连接参数
    #@Params
    #$1:分隔符字符串
    #${@:2}:要联接的参数
    #@输出
    #>&1:由分隔符字符串分隔的参数
    数组::join(){
    (($)| |返回1 |至少需要分隔符
    本地--delim=“$1”str IFS=
    转移
    str=“${*/#/$delim}”#使用前缀分隔符展开参数(空IFS)
    echo“${str:${delim}}”#没有第一个分隔符的echo
    }
    declare-a my_数组=(“巴黎”“柏林”“伦敦”“布鲁塞尔”“马德里”“奥斯陆”)
    数组::连接“,”${my_数组[@]}”
    数组::联接'*'{1..9}|bc|1*2*3*4*5*6*7*8*9=362880阶乘9
    declare-a null_数组=()
    数组::join'==零的最终分隔符='“${null_数组[@]}”
    
    输出:

    Paris, Berlin, London, Brussel, Madrid, Oslo
    362880
    
    

    ${${ids[*]}//}
    是一个语法错误,仅此而已。不知道您试图在这里实现什么。试图在1跳中实现变量替换,它永远不会起作用…相关:。因此,这是一个typeof和变量替换错误${需要字符串类型的变量,但没有收到。感谢您的详细解释。您也可以跳过字符串赋值,仍然可以使用
    printf'%smyDelim'${array[@]}将数组转换为带有任意分隔符的分隔字符串,而不必是单个字符
    。可以通过管道将分隔符
    myDelim
    的最后一个实例导入到
    sed-e的/myDelim$/'
    ,但这很麻烦。更好的主意?@JonathanY。如果是这样,请使用
    printf-v myVar'%smyDelim'${array[@]};myVar=“${myVar%myDelim”
    而不是fork to
    sed
    ,除非它不会跳过变量赋值,例如,当使用
    printf
    为另一个可执行文件提供输入参数时。我知道赋值一个变量可能更快、更便宜;只是感觉不那么优雅。@F.Hauri在myDelim周围必须有双引号。你还必须有$symbol.Lite这个“%s$myDelim”这对我来说是最简单的,因为我在数组元素之间有>1个字符串,而且在我的情况下,我也不需要删除“多余的”。工作起来很愉快!
    printf-v strng“'%s',\n”${thearray[*]}
    :)同意,使用最简单。此外,如果您使用带有语法突出显示的IDE,这也是一个用户友好的选项,不会像中那样拾取
    eval
    'd语法。非常方便,谢谢!也许
    join
    会是一个更合适的名称,不过,与
    join
    函数的工作方式一致?@theudeabides无法直接命名它
    join
    ,因为这与连接文件行的现有命令名冲突。*facepalm*-啊,是的,当然。我忘了。
    {
    
        # OIFS="$IFS"
        # IFS=$': \t\n'
        # unset array 
        # declare -a array=($(echo root:x:0:0:root:/root:/bin/bash))
    
        IFS=: read -a array < <(echo root:x:0:0:root:/root:/bin/bash)
    
        echo 1 "${array[@]}"
        echo 2 "${array[*]}"
        OIFS="$IFS" IFS=:
        echo 3 "${array[@]}"
        echo 4 "${array[*]}"
        IFS="$OIFS"
    }
    1 root x 0 0 root /root /bin/bash
    2 root x 0 0 root /root /bin/bash
    3 root x 0 0 root /root /bin/bash
    4 root:x:0:0:root:/root:/bin/bash
    
    ids=( 1 2 3 4 )
    IFS=\| eval 'lst="${ids[*]}"'
    
    ids=(1 2 3 4)                     # create array
    printf -v ids_d '|%s' "${ids[@]}" # yields "|1|2|3|4"
    ids_d=${ids_d:1}                  # remove the leading '|'
    
    Paris, Berlin, London, Brussel, Madrid, Oslo
    362880