ファイルを行ごとに切り捨てる方法は?


13

多数のファイルがありますが、そのうちのいくつかは非常に長いファイルです。ファイルの末尾を削除して、サイズが大きい場合は特定のサイズに切り捨てたいと思います。しかし、私は行全体を削除したいだけです。これどうやってするの?Linuxツールチェーンで処理されるようなもののように感じますが、適切なコマンドがわかりません。

たとえば、300バイトの行を持つ120,000バイトのファイルがあり、10,000バイトに切り詰めようとしているとします。最初の33行は残り(9900バイト)、残りはカットされます。10,000バイトで正確にカットしたくないのは、部分的な行が残るためです。

もちろん、ファイルの長さは異なり、行はすべて同じ長さではありません。

理想的には、結果のファイルを少し長くするのではなく、少し短くする(ブレークポイントが長い行にある場合)が、それはそれほど重要ではなく、それが簡単であれば少し長くすることができます。ファイルに直接変更を加えたいのですが(おそらく、新しいファイルを別の場所にコピーし、元のファイルを削除し、新しいファイルを移動しましたが、それはユーザーのPOVと同じです)。データを多数の場所にリダイレクトしてから元に戻すソリューションにより、ファイルが破損する可能性がありますが、それを避けるために...


回答を削除しました…Bytesのファイルサイズはあまり明確ではなかったと思いますが、申し訳ありません。たぶん、あなたはあなたの質問を編集し、その部分を明確にすることができます(例で)?
slhck

@slhck:私が不明瞭だったからといってあなたが担当者を失うのを見てごめんなさい...私がそれを修正できるかどうか見てみましょう。
チャールズ

心配する必要はありません。すみません、すみません:)
slhck

回答:


1

sed/ wc場合は複雑さは、前の回答で回避することができますawk使用されています。OPから提供された例を使用(10000バイトの前に完全な行を表示):

awk '{i += (length() + 1); if (i <= 10000) print $ALL}' myfile.txt

そのバイトが行末にない場合、10000番目のバイトを含む完全な行も表示します。

awk '{i += (length() + 1); print $ALL; if (i >= 10000) exit}' myfile.txt

上記の答えは次のことを前提としています。

  1. テキストファイルは、Unix行ターミネータ(\n)です。Dos / Windowsテキストファイル(\r\n)の場合、変更length() + 1するlength() + 2
  2. テキストファイルにはシングルバイト文字のみが含まれます。マルチバイト文字がある場合(ユニコード環境など)、LC_CTYPE=Cバイトレベルで解釈を強制するように環境を設定します。

14

sedアプローチは罰金ですが、すべての回線でループしていません。保持する行数がわかっている場合(例としてここでは99を使用しています)、次のようにできます。

sed -i '100,$ d' myfile.txt

説明:sedは正規表現プロセッサーです。-i指定されたオプションを使用すると、単にファイルを読み取って結果を標準出力に書き込むのではなく、ファイルを直接処理します(「インライン」)。100,$「100行目からファイルの終わりまで」という意味です。その後にコマンドが続きdます。これは、おそらく「delete」を表すために正しく推測したものです。つまり、コマンドは「100行目からmyfile.txtのファイルの最後までのすべての行を削除する」という意味です。99行を保持するため、100が削除される最初の行です。

編集:一方、たとえば最後の 100行を保持するログファイルがある場合:

[ $(wc -l myfile.txt) -gt 100 ] && sed -i "1,$(($(wc -l myfile.txt|awk '{print $1}') - 100)) d" myfile.txt

ここで何が起こっていますか:

  • [ $(wc -l myfile.txt) -gt 100 ]:ファイルに100行を超える場合にのみ以下を実行します
  • $((100 - $(wc -l myfile.txt|awk '{print $1}'))):削除する行数を計算する(つまり、保持する(最後の)100を除くファイルのすべての行)
  • 1, $((..)) d:最初の行から計算された行までのすべての行を削除します

編集:質問が編集されて詳細が追加されたため、この追加情報も回答に含めます。追加された事実は次のとおりです。

  • 特定のサイズがファイルに残ります(10,000バイト)
  • 各行には特定のサイズ(バイト単位)があります(例では300バイト)

これらのデータから、残りの行数を「/」として計算することができます。これは、例では33行を意味します。計算のシェル用語:($((size_to_remain / linesize))少なくともBashを使用するLinuxでは、結果は整数です)。調整されたコマンドは次のようになります。

# keep the start of the file (OPs question)
sed -i '34,$ d' myfile.txt
# keep the end of the file (my second example)
[ $(wc -l myfile.txt) -gt 33 ] && sed -i "1,33 d" myfile.txt

サイズは事前にわかっているので、sedコマンドに埋め込まれた計算の必要はありません。ただし、柔軟性を高めるために、一部のシェルスクリプト内では変数を使用できます。

ファイルサイズに基づく条件付き処理の場合、次の「テスト」構築を使用できます。

[ "$(ls -lk $file | awk ' {print $5}')" -gt 100 ] &&

つまり、「のサイズ$fileが100kB を超える場合、do ...」(ls -lkkBの位置5にファイルサイズをリストするため、awkこれを正確に抽出するために使用されます)。


OPは、行単位の長さだけでなく、特定のバイトサイズに基づいてファイルをカットしようとしています。を含む回答を削除しましたhead -n
slhck

@slhck通知ありがとうございます。はい、OPは意図をより明確にするために質問を編集しました。彼は各行のバイト数を計算する手段を持っているので、私の答えは原則として有効です-残りの行数を計算し、ファイルを処理するために私のアプローチを使用できるからです。たぶん私は私の答えの中でそれについて短いコメントをします。
イジー

いいえ-サイズは事前にわかりません。それは一例でした。各ファイルのサイズは異なり、行の長さは不規則です。一部のファイルは、完全に切り捨てる必要はありません。
チャールズ

ああ、また...さて、いくつかのことは明確に説明するのが難しいです(ファセットが多すぎる)。切り捨てる必要のないファイルについては、おそらくファイルサイズに基づいていますか?それをカバーできます。しかし、平均的な行サイズがわからない場合、この部分は難しくなります。現時点では簡単な解決策(オーバーヘッドが多すぎることはありません)は考えられません。
イジー

私が現在思いつくことができるのは、たとえば最初のn行を取得し、それらに基づいて平均長を計算し、この値を使用することです。それはあなたを助けますか?
イジー

0

これを行うためのコマンドが見つからないため、簡単なスクリプトを作成しました(テストされていません)。

#!/bin/sh

# Usage: $0 glob.* 25000
# where glob.* is a wildcard pattern and 25000 is the maximum number of bytes.

limit=20000
tmp=/tmp/trim
[[ "$2" == +([0-9]) ]] || limit=$2
limit=`expr $len + 1`
for file in $1;
do
    [[ `wc -c $file` -lt $limit ]] && continue
    head -c $file > $tmp
    sed '$d' $tmp
    $tmp > $file
done

-1

linuxコマンドsedを使用して、ファイルから行を削除できます。次のコマンドは、filename.txtの最後の行を削除します。

sed '$d' filename.txt

awkまたはfindを使用すると、sedコマンドに一致するパターンを検索できます。最初にawkで検索するか、短縮したいファイルを見つけてから、sedで行を削除できます。


-1

私は尾で似たようなことをしました。この場合、最後の10,000行のみを保持するには:

TMP=$(tail -n 10000 /path/to/some/file 2>/dev/null) && echo "${TMP}" > /path/to/some/file
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.