7

I have my string in $LINE and I want $ITEMS to be the array version of this, split on single tabs and retaining blanks. Here's where I'm at now:

IFS=$'\n' ITEMS=($(echo "$LINE" | tr "\t" "\n"))

The issue here is that IFS is one-or-more so it gobbles up new-lines, tabs, whatever. I've tried a few other things based on other questions posted here but they assume that there will always be a value in all fields, never blank. And the one that seems to hold the key is far beyond me and operating on an entire file (I am just splitting a single string).

My preference here is a pure-BASH solution.

4

5 に答える 5

5

IFS文字が空白の場合、1 つまたは複数のみです。非空白文字は単一の区切り文字です。したがって、単純な解決策は、文字列にないと確信できる非空白文字がある場合、タブをその文字に変換してから分割することです。

IFS=$'\2' read -ra ITEMS <<<"${LINE//$'\t'/$'\2'}"

残念ながら、「入力に のインスタンスがない」などの仮定は\2、長期的には失敗する傾向があり、「長期的には」は「最悪の場合」に変換されます。したがって、次の 2 つの手順で行うことができます。

IFS=$'\2' read -ra TEMP < <(tr $'\t\2' $'\2\t' <<<"$LINE")
ITEMS=("${TEMP[@]//$'\t'/$'\2'}")
于 2013-11-01T02:48:47.983 に答える
2

1 つの可能性: で分割する代わりに、オプションをIFS使用して、文字列から「行」をタブで終了します。ただし、文字列もタブで終わっていることを確認する必要があります。そうしないと、最後の項目が失われます。-dread

items=()
while IFS='' read -r -d$'\t' x; do
   items+=( "$x" )
done <<< $'   foo   \t  bar\nbaz \t   foobar\t'

printf "===%s===\n" "${items[@]}"

余分なフィールドを追加せずに末尾のタブを確保するには、

if [[ $str != *$'\t' ]]; then str+=$'\t'; fi

必要であれば。

于 2013-11-01T12:32:26.170 に答える
-1
line=$'zero\tone\ttwo'
IFS=$'\t' read -a arr <<< "${line}"
declare -p

出力は

declare -a arr='([0]="zero" [1]="one" [2]="two")'

ノート。これは の改行を扱いませんline

于 2014-10-30T08:23:57.927 に答える
-1

タブでのみ分割し、改行やその他の面白い記号がある場合は保持する純粋な bash ソリューション:

IFS=$'\t' read -r -a arr -d '' < <(printf '%s' "$line")

それを試してみてください:

$ line=$'zero\tone with\nnewlines\ttwo\t     three   \n\t\tfive\n'
$ IFS=$'\t' read -r -a arr -d '' < <(printf '%s' "$line")
$ declare -p arr
declare -a arr='([0]="zero" [1]="one with
newlines" [2]="two" [3]="     three   
" [4]="five
")'

ご覧のとおり、これは問題なく機能します。すべて (スペース、改行など) が保持され、タブ文字でのみ分割されます。

欠点が 1 つあります。「空のフィールド」を処理しないことlineです。で空のフィールドを取得することを期待しますが、arrそうではありません。

あまり目立たない別の欠点があります: の戻りコードread1であるため、技術的には、Bash の場合、このコマンドには失敗があります。set -eまたはを使用していない限り、これはまったく問題でset -Eはありませんが、とにかくこれは推奨されません (したがって、使用しないでください)。

これら 2 つの小さな欠点を許容できる場合は、これが理想的なソリューションになる可能性があります。

後者は末尾に改行を挿入するため、 feedでは< <(printf '%s' "$line")なく andを使用していることに注意してください。<<< "$line"read

于 2014-10-30T09:25:17.020 に答える