Bashでタブ区切りのレコードを書き換えると機能しません。

Bashでタブ区切りのレコードを書き換えると機能しません。

bashを使用してタブ区切りのCSVファイルを解析し、レコードの内容を確認し、特定の条件を満たす場合は配列に追加する必要があります。デフォルトでは、CSVファイルでレコードを処理する前にフィルタリングしたいと思います。

私の考えは、ファイルの各行を取得し、各フィールドを配列に入れることです。その後、配列を調べて、レコードが特定の条件(例:field3 = "value"など)を満たしていることを確認できます。その場合は、タブ区切りの行を「再作成」して新しい配列に追加します。

これが失敗したように見えるのは、私が作っている行ですrecord。後でタブの代わりにスペースでレコードを区切ったのとdetails同じサイズであるため、タブの代わりにスペースを追加するようです。

datafile=path/to/data.csv
records=()
header=$(head -n 1 $datafile)
IFS=$'\t' read -r -a fields <<< "$header"

while IFS=$'\t' read -r -a documents; do

    # processing to determine if current row in csv file matches certain criteria
    # if it does, the following will happen

    for r in ${documents[@]}; do record+="$r"$'\t'; done #appending space instead?
    records+="$record"
done < $datafile

for r in "${records[@]}"; do
    IFS=$'\t' read -r -a details <<< "$r"

    # size of details here is as if record is separated by spaces instead of tabs

    for i in "${!fields[@]}" ; do
        echo "${fields[i]}: ${details[i]}"
    done
done

例: このレコードがプロセスの場合:

Hello World  [TAB]  nice weather we are having today  [TAB]  do you agree?

サイズはdetails3でなければなりませんが、11になります。なぜ?

ベストアンサー1

あなたの質問が取り上げられましたスペースやその他の特殊文字が原因でシェルスクリプトが停止するのはなぜですか?。ここで何が起こっているのか簡単に説明します。

犯人はですfor r in ${documents[@]}。変数拡張が引用されていないので、「split + glob」操作を使用してください。つまり、各配列要素の値は値に基づいて単語に分割され、IFS各単語はワイルドカードパターンとして扱われます。IFS期間のみ設定したためread(参照"IFS=;"代わりに「IFS = Read」が頻繁に使用されるのはなぜですか?)、IFSこのときの値は空白を含むデフォルト値です。また、このような内容を含むフィールドがある場合は、foo *現在のディレクトリのファイル名が表示されることがあります。解決策は、for r in "${documents[@]}"これが配列を繰り返す標準的な方法です。二重引用符は、分割やワイルドカードなしで配列を直接変数の逆参照に変換し、[@]各配列要素が別々の単語に配置されるようにします。

スクリプト全体を設定するとIFS=$'\t'問題が解決するように見えますが、実際には問題の半分しか解決しません。問題を防ぎません${documents[@]}。閉じるワイルドカードを使用できますが、set -f二重引用符を使用する方が明確です。

おすすめ記事