【问题标题】:Bash shell script -- split string INCLUDING the delimeter?Bash shell 脚本——拆分字符串包括分隔符?
【发布时间】:2011-04-03 15:58:21
【问题描述】:

我想知道是否有一种简单的方法可以将字符串拆分为数组并包含分隔符?

例如:

foo = "a;b;c;d;" 

将解析为:

"a;" "b;" "c;" "d;"

似乎大多数函数都去掉了分隔符。

编辑:我最终需要的不是回显输出,而是一个我可以稍后在脚本中操作的数组。此外,如果字符串可以从文本文件中读取,这可能是最简单的。

【问题讨论】:

  • foo = "something" 已经无效。与大多数其他语言相比,赋值运算符周围不支持空格。两者都必须删除。
  • 只是将分隔符附加到项目的末尾会不会有问题? (如果您知道如何拆分,不包括分隔符)
  • 是的,抱歉,foo="something" 是正确的语法。谢谢!

标签: bash shell


【解决方案1】:
foo="a;b;c;d;"
for z in $(echo $foo | sed -r 's/([^;]+;)/\1 /g') 
do
  echo $z
done

a;
b;
c;
d;

(修改后) 如何制作数组:

# declare -a arr
arr=($(echo $foo | sed -r 's/([^;]+;)/\1 /g'))

注意:正如 Glenn 指出的那样,如果空白构成内容的一部分,它将失败。

我的手册说,我应该使用declare -a 来声明一个数组,但在实践中,我似乎不需要它。

【讨论】:

  • 如果数据中有空格会中断。
【解决方案2】:
declare -a Array=($(echo 'a;b;c;' |cut -d';' --output-delimiter="; " -f1-))
echo ${Array[2]}
> c;
declare -a Array=($(echo 'a;b;c' |cut -d';' --output-delimiter="; " -f1-))
echo ${Array[2]}
> c

这很糟糕,但是,嘿,它有点工作。如果您的输入中有空格,您将需要一个不同的分隔符,所以这并不理想。

【讨论】:

  • 如果数据中有空格会中断
  • 确实如此。这就是为什么我说它很恶心,需要一个不同的分隔符来支持空格......
  • 这完全符合我的需要(丑陋的很好)......可以修改它以从文件中读取输入字符串吗?如果我只是将 "echo "a;b;c;" 更改为 "cat somefile.txt" 会起作用吗?
【解决方案3】:
foo='foo bar;abc def;ghi;jlk;'
oldIFS="$IFS"
IFS=\;
declare -a ary=($foo)
for ((i=0; i<${#ary[@]}; i++)); do ary[$i]="${ary[$i]}$IFS"; done
IFS="$oldIFS"
echo "${ary[1]}"  # ==> "abd def;"

【讨论】:

  • 听说修改 IFS 值有点问题,不是吗?
  • @Dave: IFS 非常适合在给定分隔符上拆分字符串。只需确保在操作结束时将其恢复为原始值即可。
  • @Dave 如果您不注意恢复它,那将是不确定的。在子shell(如{ here })中执行此操作,您会很安全
  • @sehe,一个子shell是( this ) -- { this; }在当前shell中。
  • @glenn: 好点,只对了一半;它可以在当前shell中。就我的使用而言,它从来都不是 :) 但你教会我以后不要依赖它
【解决方案4】:

Ruby(1.9+)

$ array=( $(echo "a;b;c;d;" | ruby -e 'gets.chomp.scan(/(\w;)/).each{|x|print "%s " % x}') )
$ echo ${array[0]}
a;
$ echo ${array[1]}
b;
$ echo ${array[2]}
c;
$ echo ${array[3]}
d;

【讨论】:

    【解决方案5】:

    您可以更改函数内部的 IFS 值,以使该函数外部的 IFS 值保持不变。

    您也可以在不循环的情况下将字符串附加到每个数组元素。

    (
    printf '%q\n' "$IFS"
    splitButKeepDelim() {
      declare IFS="$1"    # limit scope of IFS
      array=( ${2} )      # hardcoded array name
      IFS=""
      array=( "${array[@]/%/;}" )  # append a ';' to every array item
      return 0
    }
    unset array
    splitButKeepDelim ';' 'a;b;c;d;'
    printf '%s\n' "${array[@]}"
    printf '%q\n' "$IFS"
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-31
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多