ファイルが多数あり、そのうちのいくつかは非常に長いです。ファイルの末尾を削除してサイズが大きい場合は、特定のサイズに切り詰めたいと思います。しかし、私は行全体を削除したいだけです。これどうやってするの? Linuxツールチェーンで処理されるようなもののように感じますが、適切なコマンドがわかりません。
たとえば、300バイトの行がある120,000バイトのファイルがあり、それを10,000バイトに切り詰めようとしているとします。最初の33行はそのまま(9900バイト)、残りは切り捨てます。行を部分的に残すため、正確に10,000バイトでカットしたくありません。
もちろん、ファイルの長さは異なり、行はすべて同じ長さではありません。
理想的には、結果のファイルは少し長くなるのではなく少し短くなります(ブレークポイントが長い行にある場合)が、それほど重要ではなく、それが簡単であれば少し長くなる可能性があります。変更をファイルに直接適用したいと思います(おそらく、新しいファイルが別の場所にコピーされ、元のファイルが削除され、新しいファイルが移動されますが、ユーザーのPOVから同じです)。データを一連の場所にリダイレクトし、その後ファイルを破損する可能性を招く解決策は、それを回避したいのですが...
sed
を使用すると、以前の回答でwc
/awk
の複雑さを回避できます。 OPから提供された例を使用して(complete 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
_
上記の答えは以下を前提としています:
\n
_)です。 Dos/Windowsテキストファイル(_\r\n
_)の場合、length() + 1
をlength() + 2
に変更しますLC_CTYPE=C
_を設定して、バイトレベルで解釈を強制します。sed
アプローチは問題ありませんが、すべての行をループすることはできません。保持する行数がわかっている場合(例として、ここでは99を使用しています)、次のように実行できます。
_sed -i '100,$ d' myfile.txt
_
説明:sed
は正規表現プロセッサーです。オプション_-i
_を指定すると、ファイルを読み取って標準出力に書き込むだけでなく、直接( "インライン")でファイルを処理します。 _100,$
_は単に「100行目からファイルの終わりまで」を意味し、その後にコマンドd
が続きます。これはおそらく「削除」を表すために正しく推測したものです。つまり、コマンドは、「myfile.txtから100行目からファイルの終わりまでのすべての行を削除する」という意味です。 99行を保持したいので、100が最初に削除される行です。
編集:一方、保持したいログファイルがある場合は、たとえばlast100行:
_[ $(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
:最初の行から計算された行までのすべての行を削除します編集:質問は詳細を示すために編集されただけなので、この追加情報も回答に含めます。追加された事実は:
これらのデータから、「/」として残る行数を計算できます。この例では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
コマンドに埋め込む計算は必要ありません。ただし、柔軟性を高めるために、一部のシェルスクリプトでは変数を使用できます。
ファイルサイズに基づく条件付き処理の場合、次の「test」構成を使用できます。
_[ "$(ls -lk $file | awk ' {print $5}')" -gt 100 ] &&
_
つまり、「_$file
_のサイズが100kBを超える場合は、次のようにします...」(_ls -lk
_は、位置5のファイルサイズをkBで示します。したがって、awk
を使用してこれを正確に抽出します。 )。
これを行うコマンドが見つからないので、簡単なスクリプトを作成しました(テストされていません)。
#!/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