Linuxでファイルの空白スペースを確認する方法の実務上の結論は「非表示文字はsed -n lでescape表示し、目的別のgrepでtrailing spaceやCRLFを検出します。確認段階では自動置換せず、encodingと正式なformatを確定します。」です。「空白」をspace、tab、CR、Unicode whitespace、末尾blankのどれとするか先に定義します。表示しにくいbyteはsed lとodで確かめ、検出工程から自動置換を分離します。
space・tab・改行・Unicode空白の分類
『空白』にはASCII space、tab、CR、LF、末尾blank、blank line、NBSP、全角spaceなどがあり、programming languageやdata formatで意味が異なります。まず問題にする種類と位置を定義し、目視だけで判定しません。indentのtabを禁止する規則と、文字列data内のspaceを変更する規則は別です。
sed -n ‘l’はline endingやtabを可視化し、grepの固定patternまたは適切な正規表現で候補行を絞ります。od -An -tx1cはbyte確認に使えます。POSIX character classの[:space:]はlocaleの影響を受け、Unicode normalizationはgrepだけで十分に扱えない場合があります。対象言語のformatter、linter、parserを優先します。
探すblankの種類と構文上の意味を定義する
- 対象encodingとline endingを確認する
- 探すwhitespaceの種類を定義する
- trailing、leading、blank lineの許容規則を決める
- 生成toolとformatterの仕様を確認する
source code、Makefile、YAMLでは同じtabやspaceでも意味が違います。対象grammarとencodingが未確定ならCI違反にせず、CRLF fixtureとUnicode fixtureを用意して、byte規則かparser規則かを決め直します。
sed l・grep・odで不可視byteを特定する
非表示文字を可視化
sed -n '1,80l' -- ./config.txt
tab、CR、line終端をescape表現で読みます。
行末spaceとtabを検索
grep -nE -- '[[:blank:]]+$' ./config.txt
一致なし1とerror 2を終了codeで分けます。
CRLFのCRを確認
grep -n -- $'\r$' ./config.txt
BashのANSI-C quotingを使うためinterpreterを確認します。
tabを含む行を検索
grep -n $'\t' -- ./config.txt
Makefile等ではtabが意味を持つため、存在だけで異常としません。
先頭byteをhex表示
head -c 128 -- ./config.txt | od -An -tx1c
BOMやUnicode whitespaceのbyte列を制限付きで確認します。
sed・grep・odで見えないbyteを調べる
[[:blank:]]はspaceとtab等をlocaleに応じて扱い、[[:space:]]はnewlineを含むclass定義ですがgrepはline単位です。CRLFのCR、nonbreaking space、full-width spaceは単純なASCII space検索では見つかりません。sed lの表示は診断用で原文そのものではありません。
sedの末尾記号やescape表現は診断表示であり、fileへ書かれた文字そのものではありません。CRLFではCRが行末に見え、UTF-8のNBSPや全角spaceは複数byteです。grepがmatchした行番号だけで種類を断定せず、必要な範囲をodで照合します。binary判定やinvalid byte sequenceも別statusとして記録します。
空pattern、shell quotingの誤り、locale差、binary file、改行をまたぐpattern、巨大一行で結果が変わります。grepの終了1は一致なし、2はerrorであり同じ扱いにしません。tabをspaceへ一括置換するとMakefileやdata columnを壊す可能性があり、CR削除もencodingを確認せず実行してはいけません。
CRLF・Unicode空白・grep statusを分ける
- すべてのtabをspaceへ変換する
- CRLFを文字化けと決めつける
- Unicode whitespaceをASCII space検索だけで扱う
- grep一致なしを実行失敗とする
- minified/固定幅dataへ一般formatterを使う
grep status 1はmatchなし、2はreadやregexのerrorです。CRだけを見つけてもCRLFか孤立CRかは断定せず、odで前後byteを確認します。encoding不正なら置換せず原本hashを保持してconverterへ戻します。
一括置換せずbyte位置だけを採取する
whitespace一括修正はdiffを広げ、Makefile、YAML、Python、Markdown、固定幅dataの意味を変える可能性があります。まず読み取り結果と規約をreviewし、変更する場合はcopy、formatter設定、差分、parser/test、rollbackを別段階にします。
診断段階ではsed -i、tr、global replaceを使いません。修正はversion管理下の小さな差分として生成し、format固有testとreviewを通します。secretを含むline全体をdiagnostic logへ出さず、必要なら行番号、種類、byte offsetだけを保存します。encoding変換と空白修正を同時に行わないようcommitを分けます。
検出と修正を分離したtest
space、tab、CRLF、LF、nonbreaking space、full-width space、末尾whitespace、blank lineを含むsampleを作ります。sed、grep、odの結果とbyte期待表を比較し、原本hashが不変か確認します。
ASCII space、tab、末尾blank、blank line、CRLF、LF、NBSP、全角space、combining characterを含むUTF-8 fixtureを用意します。sed、grep、od、対象formatterの出力とstatusをbyte単位の期待表へ照合します。正常indentや文字列literalを誤検知しないこと、検出commandだけでは原本hashが変わらないことも確認します。
拡張子別のwhitespace policyをCIへ固定する
CIでは対象拡張子、除外directory、許可するline ending、tab policy、末尾blank規則をrepositoryへ明記します。grep文言のlanguage差に依存せずstatusとmachine-readable formatter結果を使います。自動修正を有効にする場合も、生成差分、変更file数上限、parse test、rollback可能なcommitを完了条件にします。
検出対象に応じてlinterとparserを選ぶ
単純なASCII末尾blankはgrepやlinter、非表示byteの調査はsed lとod、Unicodeや構文依存の空白はparser/formatterを選びます。混在encodingがあるrepositoryでは、まずencoding移行計画を立てます。空白を見つけることと、どの表現へ統一するかは別判断としてownerと合意します。
合格はspace末尾、tab、CRLF、Unicode空白、clean fileで期待lineだけを検出し、原本hashが不変なことです。policy外形式を見つけたrunはfailにせずreview queueへ分岐します。

コメント