Linuxでテキストファイルを逆順に表示する方法と応用例の手順を先に要約すると「行の並びを末尾から表示するならtac、各行の文字並びを反転するならrevを使い分け、multibyte文字と末尾newlineをsampleで確認します。」となります。対象環境では、line順を反転するtacはGNU Coreutils、各lineのcharacter順を反転するrevはutil-linuxに含まれ、処理単位も異なります。 確認ポイント:tacはrecord順、revは各行の文字順を反転し、revはutil-linuxに含まれます。
line順と文字順のどちらを反転するか決める
入力source、期待する出力型、許容する0件、処理上限を決めます。作業端末のlocale、timezone、encodingが結果へ影響する場合は、その値も証跡に含めます。
- line順かline内文字順かを定義する
- text encodingとlocaleを確認する
- 末尾newlineと空lineの扱いを決める
- 巨大fileでmemoryとI/Oを測る
0件を成功扱いするかは用途で決めます。不明な場合は後続処理を止め、入力sourceを再確認します。
標準出力か別fileだけへ反転結果を出す
表示commandでもredirect先を原本と同じにするとshellが先にfileをtruncateします。必ず別pathへ出力し、必要ならhashとline countで検証後に利用します。構造化dataは専用parserでrecord境界を保ちます。
tac・rev・tailを目的別に実行する
line順を逆に表示
tac -- ./events.log
最後のrecordから先頭へ表示し、原本は変更しません。
各lineの文字列を反転
rev -- ./sample.txt
lineの順番自体は変わりません。
最後の十行だけを時系列へ戻す
tail -n 10 -- ./events.log | tac
末尾10件を取得してから古い順へ並べます。
区切り文字単位でtacを使う
tac -s '---' -- ./records.txt
separatorがrecord内容にも現れないことをsampleで確認します。
結果を別fileへ保存
tac -- ./input.txt > ./input.reversed.txt
cmp -s -- ./input.txt ./input.reversed.txt; printf 'cmp_rc=%s\n' "$?"
原本と出力先を別にし、誤ったin-place上書きを避けます。
空file・末尾newline・巨大lineを区別する
tacはrecord separatorを基準にfileを逆方向へ連結し、既定はnewlineです。revは各lineのcharacter順を反転しますが、Unicode grapheme clusterと人が見る一文字が一致しない場合があります。JSON、CSV、log continuationはline逆順で意味を壊す可能性があります。
一件の成功例に寄せず、境界値と失敗例を同じsample setで試します。
tacとrevを取り違えない
- tacとrevを同じ逆順処理と考える
- 原本へ直接redirectして空にする
- Unicode結合文字を一文字として期待する
- multiline recordをline単位で壊す
- 末尾newlineの差を無視する
最小sampleで再現しない問題を本番dataだけで試行錯誤しません。
ASCII・日本語・結合文字で往復確認する
ASCII、日本語、emoji結合、空line、末尾newlineなし、複数line recordのsampleを用意します。tacを二回、revを二回適用した結果と原本をcmpし、用途上のrecord境界も確認します。比較時はbyte数、line数、末尾newline、localeを記録し、表示端末のfont差をdata破損と取り違えないよう、必要に応じてhexdump等の読み取り結果も併記します。
更新後は同じsampleを再実行し、既定値や出力schemaの差をreviewします。
原本と同じredirect先なら実行を止める
Linux textの逆順表示の開始記録には「line順かline内文字順かを定義する」を最初に置きます。続けて「text encodingとlocaleを確認する」を確認すると、対象違いと環境違いを作業前に分けられます。
対象範囲を確定する段階では「末尾newlineと空lineの扱いを決める」が判断材料になります。また「巨大fileでmemoryとI/Oを測る」を満たさない場合は、技術的に実行できても運用上の準備不足です。
実例のうち「line順を逆に表示」はbaselineを得る用途、「各lineの文字列を反転」は対象をさらに具体化する用途として使い分けます。両方の出力を同じ形式へ無理に整形せず、元の型と件数を保持したまま比較します。期待値は画面の見た目ではなく、対象ID、path、時刻など再照合できる列で定義します。
tail -n 10 | tac の確認には、10行未満、空行、末尾改行なし、マルチバイト文字を含む検証ファイルを使います。追記中のログを別々の時刻に読み直すと対象行そのものが変わるため、再現性が必要なら一度読み取った内容を安全な一時ファイルへ固定してから比較します。区切り文字を変える場合は、その文字が本文に含まれないことも先に確かめます。
逆順結果をファイルへ残すとき、> は既存内容を置き換え、>> は追記します。検証では既存名を避けた専用ディレクトリへ新しい出力名を使い、作成前後の件数と先頭・末尾行を確認してください。元ファイルを入力と出力へ同時指定すると、シェルが先に出力側を空にするため、同じパスへ直接リダイレクトしません。
再試行の前に、行順を逆にする tac と各行の文字順を逆にする rev を取り違えていないか確認します。原本と同じpathへ直接redirectすると、command開始前に内容が空になるため禁止します。結合文字やemojiを含む文字単位の反転は見た目どおりにならない場合があり、用途を限定します。
結果を保存するなら、新規の検証用pathへ出力し、元ファイルのmode・所有者・timestampを変更しません。ログに個人情報や秘密値がある場合は、反転結果も同じ機密区分で扱います。複数行recordを単純な行単位で反転するとrecord構造が壊れるため、入力形式の境界を先に確認します。
再現記録にはtac/revの実装とversion、locale、入力のhash・byte数・行数、使用した区切り、終了値を残します。出力についても行数と先頭・末尾を照合し、必要ならhashを記録します。表示だけならrollbackはなく、新規出力を作った場合だけそのpathを管理します。
完了条件は、tacで行集合が変わらず順序だけ逆転し、revでは各行の処理結果がfixtureの期待値に一致することです。空行、10行未満、末尾改行なしを含めて確認し、元ファイルが変更されていないことをhashまたはmetadataで確かめます。
大容量fileは末尾の限定範囲から確認する
全体を逆順表示すると端末が大量出力で埋まるため、まず tail -n 20 -- 対象 | tac のように範囲を限定します。期待した順序を確認してから必要な件数へ広げ、標準エラーに読み取り失敗がないことも確かめます。元ファイルを変更しない読み取りpipelineとして実行し、出力保存が必要な場合だけ別pathを指定してください。
revの確認では、入力をもう一度revへ通して元の各行へ戻るかを小さなsampleで照合します。ただし、人が一文字に見える結合文字やemojiの連字は複数のcode pointから成るため、見た目の単位を保つ反転とは限りません。識別子や署名対象のdataへ適用する前にlocaleと文字表現を固定し、元ファイルを変更せず標準出力または別ファイルで比較します。

コメント