タブを区切り文字として bash の行を配列に分割する

タブを区切り文字として bash の行を配列に分割する

タブで区切られた次の形式のファイルがあります。

a   k   testis  adult   male    8 week  rRNA
b   k   testis  adult   male    8 week  rRNA
c   k   testis  adult   male    8 week  rRNA

各行に対していくつかのタスクを実行したいので、whileループを使用します。タブの各行を分割し、6番目の列と見なさ8 weekれる内容を変数に保存したいと思います。このコードを使用していますが、欲しいものを取得できません

while read -r line; do tmp=(${line///}); col6=${tmp[5]}; echo "$col6"; done < file.txt

これは私に8別のいいえを与えます8 week。 8週間は8と週の間にスペースがあるので、タブで行を分割したいと思います。

答え1

配列の割り当ては、デフォルトでタブを含む含まれるすべての文字tmp=(${line///})に値を分割します。IFSそして空間改行文字。 (空の置換が何であるかわかりません。)タブでのみ分割するには、次のように設定しますIFS

foo=$'a\tk\testis\tadult\tmale\t8 week\tRNA'
IFS=$'\t'
tmp=($foo)
echo "${tmp[5]}"

それでもワイルドカードが問題になり、すでに使用しているので、これに基づいて入力行を分割し、結果フィールドを次のように保存する(Bashでのみksh / zsh / yashに置き換えます)をwhile read使用できます。名前付き配列:read -a tmp-a-AIFS

$ while IFS=$'\t' read -r -a tmp ; do
    echo "${tmp[5]}"
done <<< $'a\tk\testis\tadult\tmale\t8 week\tRNA'

印刷されました8 week。もう1つの利点は、変更がスクリプトの残りの部分ではないIFS期間にのみ適用されることです。read

ただし、readタブを区切り文字として使用すると、空のフィールドが削除されます。では、交換することで、このようなことが発生するのを防ぐzshことができます。IFS=$'\t'IFS=$'\t\t'

もちろん、フィールドの数/意味を知っていれば、readそれを別の名前付き変数に分割できます。

... IFS=$'\t' read -r col1 col2 col3 ...

または、この列のみを印刷するには、次を使用しますcut

cut -d$'\t' -f 6  < file.txt

空の列があり、cut -d$'\t'別のIFS=$'\t'動作をする場合。 Cut は、個々のタブをそれぞれ異なる区切り文字として扱い、read連続タブを 1 つの区切り文字として扱います。一つスプリッタ。つまり、文字列はfoo<tab><tab>bar2つの列として読み取られますreadが、3つの列では読み取られませんcut

タブの設定は変更できませんが、印刷文字は常に別の区切り文字として認識されるため、データに表示されない一部の文字でタブを変更してから、左右の区切り... | tr '\t' : | IFS=: read -r -a tmp記号として使用できます。

関連情報