创建一个将 IFS 设置为不同值的数组

创建一个将 IFS 设置为不同值的数组

我正在尝试构造一个数组并以这种格式写入文件,即文件的内容应该是这样的

hero_pairscore=( askdjfh sdf,sdlkfj lksf,dfgdf,dsflkgj,asdlkf ....)

其中元素由 分隔comma。我为此编写了以下代码。

#!/bin/bash
#set -x

hero_pairscore=()
while read line
do

$( IFS=",";hero_pairscore+=( "$line" )
done < true_pairscore.txt

echo "hero_pairscore=( ${hero_pairscore[@]} )" > embed.txt

但生成的文件仅包含此hero_pairscore=( ).我的代码有什么问题以及如何纠正它以提供所需的输出?

答案1

您在这里需要做的就是:

  1. 设置变量。我们将使用这个:

    var="kijhg, fbjhku,,,ioy  fbjfr, kjmyhg"
    
  2. 设置$IFS并防止文件名扩展:

    IFS=, ; set -f
    
  3. set要输出的shell$@数组。

    set -- $var
    
  4. 重置父 shell$IFS和 shell 参数:

    unset IFS ; set +f
    
  5. 万岁!它甚至保留了多个重复和空格等等!

    printf %s\\n "$@"
    

    输出

    kijhg
     fbjhku
    
    
    ioy  fbjfr
     kjmyhg
    

无论如何,请相信我的话。每个不是 a 的字符,都会被保留。

转换

我特别建议使用真正的 shell 数组而不是 bash 数组,因为你可以立即转换它的拆分器。

printf %s "$*"

#OUTPUT#
kijhg  fbjhku   ioy  fbjfr  kjmyhg %

IFS=, ; printf %s "$*"

#OUTPUT#
kijhg, fbjhku,,,ioy  fbjfr, kjmyhg

因为$*具有特殊的 POSIX 指定的质量,可以在第一个字符上拆分 shell 的位置参数参数数组,$IFS因此您可以轻松地转换大量数据。您可以"quote"保护参数数组,并仍然将其拆分为您喜欢的任何单个字符。只要你第一次就做对了,那就是。

追加/前置

POSIX 还为 指定了特殊性质"$@"。除了"$1"... eval "\${$#}"每个参数的寻址形式之外,"$@"参数(当引用时)可以安全地扩展为所有 shell 参数,因为它们是最后一个,set而不管 的当前值是什么。$IFS.因此,如果您想在数组开头添加一个列表,您可以这样做:

set -- $list "$@"

到头部/尾部:

set -- $head "$@" $tail

要将阵列增加三倍:

set -- "$@" "$@" "$@"

现在总共

除非您的数据流非常大,否则以下操作可能会比您当前的操作快一点(不过,如果您正在处理文件,那么最好完全避免 shell 分割):

( set -f -- ; IFS=, ; while read -r line ; do set -- "$@" $line ; done
printf %s "$*" ) | cat >out

也许是TR?

但我不明白的是——你在做什么?您是否想用逗号替换换行符?我是说 -除了换行符之外,数据是否已经用逗号分隔?如果是这样:

tr '\n' ',' <in >out

答案2

做我该做的事思考您正在尝试执行的操作是将每个逗号分隔的字段读取true_pairscore.txt到数组变量中,您的代码没有太大问题。该行$(开头的显然IFS是错误的,会导致脚本出错(也许这就是您没有输出的原因)。除此之外,代码的主要修复只是删除周围的引号,$line因为您想要bash进行分词IFS(通常这是您使用它们来避免的):

#!/bin/bash

set -o noglob
OIFS=$IFS
IFS=","
hero_pairscore=()

while IFS= read -r line
do
  hero_pairscore+=( $line )
done < true_pairscore.txt

echo "hero_pairscore=( ${hero_pairscore[@]} )" > embed.txt

set +o noglob
IFS=$OIFS

然而,这里有一个技巧,只需两行即可完成上述操作:

IFS=$',\n' read -ra hero_pairscore -d '' <true_pairscore.txt
echo "hero_pairscore=( ${hero_pairscore[@]} )" > embed.txt

更新

如果embed.txt要在另一个 shell 中获取该文件bash,您可能需要引用写入hero_pairscore数组的每个元素。为此,请将其替换echo "hero_pairscore=( ${hero_pairscore[@]} )"为:

echo "hero_pairscore=( $(printf '"%s" ' "${hero_pairscore[@]}") )"

相关内容