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

Ash*_*win 5 bash array string

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

hero_pairscore=( askdjfh sdf,sdlkfj lksf,dfgdf,dsflkgj,asdlkf ....)
Run Code Online (Sandbox Code Playgroud)

其中元素由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
Run Code Online (Sandbox Code Playgroud)

但是生成的文件只包含这个hero_pairscore=( ). 我的代码有什么问题,如何更正它以提供所需的输出?

mik*_*erv 6

您需要做的就是:

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

    var="kijhg, fbjhku,,,ioy  fbjfr, kjmyhg"
    
    Run Code Online (Sandbox Code Playgroud)
  2. 设置$IFS并防止文件名扩展:

    IFS=, ; set -f
    
    Run Code Online (Sandbox Code Playgroud)
  3. set$@要输出的shell数组。

    set -- $var
    
    Run Code Online (Sandbox Code Playgroud)
  4. 重置父 shell$IFS和 shell 参数:

    unset IFS ; set +f
    
    Run Code Online (Sandbox Code Playgroud)
  5. 万岁!它甚至保留了多次重复和空格等等!

    printf %s\\n "$@"
    
    Run Code Online (Sandbox Code Playgroud)

    输出

    kijhg
     fbjhku
    
    
    ioy  fbjfr
     kjmyhg
    
    Run Code Online (Sandbox Code Playgroud)

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

转变

我特别推荐使用真正的 shell 数组而不是 bash 数组,因为您可以立即转换其拆分器。

printf %s "$*"

#OUTPUT#
kijhg  fbjhku   ioy  fbjfr  kjmyhg %

IFS=, ; printf %s "$*"

#OUTPUT#
kijhg, fbjhku,,,ioy  fbjfr, kjmyhg
Run Code Online (Sandbox Code Playgroud)

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

追加/预先准备

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

set -- $list "$@"
Run Code Online (Sandbox Code Playgroud)

到头/尾:

set -- $head "$@" $tail
Run Code Online (Sandbox Code Playgroud)

将您的阵列增加三倍:

set -- "$@" "$@" "$@"
Run Code Online (Sandbox Code Playgroud)

现在全部

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

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

也许是TR?

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

tr '\n' ',' <in >out
Run Code Online (Sandbox Code Playgroud)


Gra*_*eme 5

做我认为你正在尝试做的事情,即将每个逗号分隔的字段读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
Run Code Online (Sandbox Code Playgroud)

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

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

更新

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

echo "hero_pairscore=( $(printf '"%s" ' "${hero_pairscore[@]}") )"
Run Code Online (Sandbox Code Playgroud)