BashでIFSを2バイト値に設定する

BashでIFSを2バイト値に設定する

BashでIFSを2バイト値に設定するにはどうすればよいですか?

IFS=',;'

区切り記号は、区切り記号の代わりに単純な部分と/または単純な2つの,部分の間にある各部分ですか?ソリューションを提供できるようにシミュレーション/解決方法を実行するには?前にありがとう;,;

答え1

zsh代わりに(plit用)パラメータ拡張フラグをbash使用して切り替えることができます。ss

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

これは分けるいいえ定義するはIFS分割(単一文字のみを含む)ではなく空の文字列foo,;に分割されます。foofoobash

また、bash(and zsh、すべてのシェルではありませんが)でスプレー数値~の$IFS, いいえバイト。たとえば、を使用すると、IFS='é'2バイトでエンコードされたロケール(たとえば、文字が最も一般的なUTF-8にマップされるロケール)でもStéphane分割されます。Stphaneé

答え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は単一文字区切り文字のセットなので、IFS=,;または;すべて,区切り文字として使用され、a,b,;c;d5つのフィールドがあります。その組み合わせを単一の区切り文字としてのみ使用するには、,;手動で実行する必要があります。 1つの方法は、,;ペアを入力の単一文字に置き換えることですIFS

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

${s//,;/#}すべての部分文字列を,;次に置き換え#、引用符なしで結果を展開します。これで、配列にsumがfields含まれます。また、生成された単語をglob(ファイル名ワイルドカード)として使用することに注意してください。これを防ぐために/を使用したいかもしれませんが、に割り当てられているだけでなく、グローバル効果もあることに注意してください。a,bc;dset -fset -o noglobIFS

sedまたは、特に開始するパイプラインがある場合は、次のものを使用できます。

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

関連情報