在 Bash 中将 IFS 设置为两个字节值

在 Bash 中将 IFS 设置为两个字节值

如何在 Bash 中将 IFS 设置为两个字节值?

IFS=',;'

将分隔位于两个 simple,和/或 simple之间的每个部分,;而不是作为,;分隔
符 如何模拟/解决方法,以便给出解决方案?之前谢谢

答案1

您可以切换到zsh而不是bash使用它的s(用于split)参数扩展标志:

$ string='foo,;bar,;,;baz'
$ words=("${(@s[,;])string}")
$ typeset -p words
typeset -a words=( foo bar '' baz )

请注意,这是分裂不是界定,foo,;将被拆分为foo和 空字符串,而不是foobash的 IFS 拆分那样(仅包含单个字符)。

另请注意,在bash(和zsh,但不是所有 shell)中,分词是在人物$IFS, 不字节。例如,使用IFS='é',Stéphane将被拆分为St甚至phaneé以两个字节编码的语言环境中(例如在字符映射为 UTF-8 的语言环境中,这是目前最常见的)。

答案2

bash(版本 4.3+)函数:

split() {
    local string=$1 fs=$2
    local -n fields=$3
    fields=()
    while [[ $string =~ (.*)"$fs"(.*) ]]; do
        fields=( "${BASH_REMATCH[2]}" "${fields[@]}" )
        string=${BASH_REMATCH[1]}
    done
    fields=( "$string" "${fields[@]}" )
}

用法:

$ string="field1,;field2,field2b,;field3a;field3b,;,;field4"
$ split "$string" ",;" result
$ declare -p result
declare -a result=([0]="field1" [1]="field2,field2b" [2]="field3a;field3b" [3]="" [4]="field4")

它会失败,就像许多实现 CSV 解析的天真的尝试一样,分隔符用引号引起来:

$ split 'Thoughtfully, he said "Hello, friend."' , x
$ declare -p x
declare -a x=([0]="Thoughtfully" [1]=" he said \"Hello" [2]=" friend.\"")

答案3

IFS是一组单字符分隔符,因此 with IFS=,;;,都将用作分隔符,并且a,b,;c;d将有五个字段。如果您只想使用该组合,;作为单个分隔符,则必须手动执行此操作。一种方法是用,;您输入的某个单个字符替换该对IFS

s='a,b,;c;d'
IFS=#
fields=(${s//,;/#})

${s//,;/#}将所有子字符串替换,;#,然后不带引号的扩展拆分结果。现在数组fields包含a,bc;d。请注意,它还将使用生成的单词作为 glob(文件名通配符)。您可能希望使用set -f/来防止这种情况set -o noglob,但请注意,除了分配给 之外IFS,它也具有全局效果。

或者你可以使用sed,特别是如果你有一个管道开始:

sed -e 's/,;/#/g'

相关内容