IFSとawk -Fを使う前に、端末がどの実装を呼び、どの対象を読むかを確認してください。Linuxでのフィールドセパレータの設定と応用例の結論は「shellで一行を分解するなら一時的なIFSとread -r、表形式はawk -Fを使い、空field、連続separator、quoted fieldをsampleで確認します。」。shellのIFSによるword splittingとawkのfield splittingは別機能で、default ruleも異なる環境で、未確認の変更を避けるための順番を示します。 確認ポイント:IFSの変更範囲は一回のreadへ限定し、quoted fieldを含むCSVには専用parserを使います。
Bashとawkのdelimiter仕様を確認する
helpのsyntax、対象端末で利用できるparameter、既定値を確認します。古いblogの画面やcommandを根拠にせず、実機結果と公式資料が一致するところから開始します。
- 入力formatと正式なseparatorを確認する
- 空fieldと連続separatorの意味を決める
- quoted separatorやescapeの有無を確認する
- 元のIFSをglobal変更しない設計にする
colon・tab・空白を別の方法で分割する
colon区切りをreadで分解
while IFS=: read -r user _ uid gid rest; do
printf '%s %s %s\n' "$user" "$uid" "$gid"
done < /etc/passwd
IFS assignmentをread一回へ限定します。
awkでseparatorを指定
awk -F '\t' '{ print $1, $3 }' ./table.tsv
TSVのfieldをawkで処理し、shell word splittingへ渡しません。
awkのFSをvariableで設定
awk -v FS='[[:space:]]+' '{ print NF, $1 }' ./data.txt
正規表現separatorとliteral separatorの違いを明示します。
IFSを安全に一時利用
parse_pair() {
local key value
IFS='=' read -r key value <<EOF
$1
EOF
printf '%s=%s\n' "$key" "$value"
}
function外のIFSへ副作用を残さない形にします。
CSVは専用parserへ渡す
python3 -c 'import csv,sys; [print(row[0]) for row in csv.reader(sys.stdin)]' < ./data.csv
quoted commaやmultiline fieldがあるCSVをIFSだけでparseしません。
IFSを一つのreadだけへ限定する
global IFS変更は後続のunquoted expansionやreadへ広く影響します。assignmentをcommand一回またはlocal scopeへ閉じ込めます。入力を分割した値をcommand名、path、SQL、shell codeへ直接連結せず、配列と引数境界を保持します。
元の設定値とservice状態を記録し、復元後の起動順やreload方法も手順へ含めます。
空field・連続separator・末尾separatorを試す
BashのIFS whitespaceはleading/trailingや連続部分に特別な扱いがあり、non-whitespace separatorとは空fieldの挙動が異なります。awkのFSはrecordをfieldへ分ける規則で、正規表現として使われる場合があります。CSVのquote ruleは単純なseparator分割を超えます。
件数を算出した母集団とfilter後の母集団を明示し、分母を途中で変えません。
CSVを単純separatorで読まない
- IFSをscript全体で変更したままにする
- quoted CSVをcommaだけで分割する
- 連続separatorで空fieldが消える条件を無視する
- awk FSとshell IFSを同一視する
- unquoted variable展開で再分割する
古い手順を残す場合は適用versionを明記し、現行手順と同じblockへ混在させません。
入力field数と出力列を照合する
先頭・末尾separator、連続separator、空field、tab/space混在、quoted comma、multiline CSVをsampleにします。期待field数と値を表にし、read、awk、専用parserの差を記録します。
監視へ渡す列を固定し、表示文言のlanguage差に依存しない判定へします。
個人情報を除いたfixtureだけを共有する
Linuxのfield separatorの開始記録には「入力formatと正式なseparatorを確認する」を最初に置きます。続けて「空fieldと連続separatorの意味を決める」を確認すると、対象違いと環境違いを作業前に分けられます。
対象範囲を確定する段階では「quoted separatorやescapeの有無を確認する」が判断材料になります。また「元のIFSをglobal変更しない設計にする」を満たさない場合は、技術的に実行できても運用上の準備不足です。
実例のうち「colon区切りをreadで分解」はbaselineを得る用途、「awkでseparatorを指定」は対象をさらに具体化する用途として使い分けます。両方の出力を同じ形式へ無理に整形せず、元の型と件数を保持したまま比較します。期待値は画面の見た目ではなく、対象ID、path、時刻など再照合できる列で定義します。
区切り処理の検証には、空フィールド、連続区切り、先頭・末尾区切り、空白を含む値を用意します。awkの FS とシェルの IFS は空白の扱いや分割規則が同じではないため、片方の結果をもう片方へそのまま当てはめません。IFSを変更する例はサブシェルに閉じるか元の値を保存・復元し、後続の引数展開へ影響が残らないことを確認します。
CSVでは引用符内のcomma、引用符のescape、改行を含むfieldがあるため、単純な awk -F, やIFS分割では一般的なCSVを正しく扱えません。入力仕様が単純であると確認できない場合は、RFC 4180相当の引用規則に対応したlibraryや製品のimport機能を使います。処理後は列数だけでなく、引用符を含む既知行が期待値へ復元されたかも照合します。
再試行の前に、IFSをscript全体で変更したままにしていないか、quoted CSVをcommaだけで分割していないか確認します。連続separator、先頭・末尾separator、空白separatorでは空fieldの扱いが変わるため、awkのFSとshellのIFSを同じ規則だとみなしません。
変数展開は引用して意図しない再分割を防ぎ、IFSの一時変更はsubshellまたは限定した read 呼び出しへ閉じます。入力に個人情報がある場合、field確認用の全行dumpを公開logへ残しません。CSVの引用規則がある入力は専用parserを使います。
再現記録にはshell・awkの実装とlocale、IFSまたはFSの値、入力encoding、fixtureのhash、各行のfield数を含めます。空fieldを見分けるため、値だけでなくindex付きで期待結果と照合します。読み取り分割だけならrollbackは不要です。
完了条件は、通常値、空field、連続separator、末尾separator、空白を含む値が仕様どおり分割されることです。引用CSVのfixtureを単純分割へ通さず、専用parserで引用符内commaと改行が一つのfieldへ復元されることを確認します。
IFSによるfield分割は、引用していないparameter展開など特定の場面で働きます。readで一行を扱う場合はread -rを使い、backslashを勝手にescapeとして消費させません。連続delimiterや行末delimiterで空fieldを保持する必要があるCSVは、shellのIFSだけでは仕様を満たせないため、引用符と改行を理解するCSV parserへ渡します。IFSを一時変更するならfunctionまたはsubshellへ範囲を限定します。

コメント