題 如何按行截斷文件?


我有大量的文件,其中一些很長。我想通過刪除文件的末尾將它們截斷到一定大小。但我只想刪除整行。我怎樣才能做到這一點?感覺就像Linux工具鏈會處理的事情,但我不知道正確的命令。

例如,假設我有一個帶有300字節行的120,000字節文件,我試圖將其截斷為10,000字節。前33行應保留(9900字節),其餘部分應切斷。我不想精確地切割10,000個字節,因為這會留下部分線。

當然,文件的長度不同,行的長度也不盡相同。

理想情況下,生成的文件會稍微縮短而不是稍長一些(如果斷點位於一條長行上),但這並不太重要,如果這更容易,可能會更長一些。我希望直接對文件進行更改(好吧,可能將新文件複製到其他地方,原始刪除,新文件移動,但這與用戶的POV相同)。將數據重定向到一堆地方然後返回的解決方案會導致破壞文件的可能性,我想避免這樣做......


13
2017-07-24 07:00


起源


刪除了我的答案......我猜字節中的文件大小不太清楚,抱歉。也許你可以編輯你的問題並澄清那部分(例如用一個例子)? - slhck
@slhck:很抱歉看到你因為我不清楚而失去了代表......讓我看看能不能解決這個問題。 - Charles
不用擔心,我應該剛問,對不起:) - slhck


答案:


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. 文本文件僅包含單字節字符。如果有多字節字符(例如在unicode環境下),請設置環境 LC_CTYPE=C 在字節級強制解釋。

1
2017-07-28 09:47





sed 方法很好,但是循環遍歷所有線路都沒有。如果你知道要保留多少行(有一個例子,我在這裡使用99),你可以這樣做:

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

說明: sed 是一個正則表達式處理器。有了選項 -i 給定,它直接處理文件(“內聯”) - 而不是只讀取它並將結果寫入標準輸出。 100,$ 只是意味著“從第100行到文件末尾” - 然後是命令 d,你可能猜對了,代表“刪除”。簡而言之,該命令意味著:“從myfile.txt刪除從第100行到文件末尾的所有行”。 100是第一行要刪除,因為你想保留99行。

編輯: 另一方面,如果您要保留日誌文件,例如該 持續 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行。計算的shell術語: $((size_to_remain / linesize)) (至少在Linux上使用Bash,結果是整數)。調整後的命令現在將顯示為:

# 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 命令。但是為了靈活性,在一些shell腳本中可以使用變量。

對於基於文件大小的條件處理,可以使用以下“test”-construct:

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

這意味著:“如果大小 $file 超過100kB,做......“(ls -lk 因此,列出位置5的文件大小(KB) awk 用來精確提取這個)。


14
2017-07-24 08:29



OP希望根據某個字節大小來剪切文件 - 而不僅僅是行的長度。我刪除了我的答案 head -n。 - slhck
@slhck感謝您的通知。是的,OP剛剛編輯了他的問題,以使意圖更加明確。由於他有辦法計算每行有多少字節,我的答案原則上仍然有效 - 因為他可以計算要保留的行數,然後使用我的方法來處理文件。也許我在答案中對此作了簡短的評論。 - Izzy
不 - 提前不知道尺寸。這是一個例子。每個文件都有不同的大小,行長度不規則。有些文件根本不需要截斷。 - Charles
哦,再說......好吧,有些事情很難解釋清楚(太多的方面)。至於不需要截斷的文件,那可能是基於文件大小的?這可以涵蓋。但是,如果甚至沒有已知的平均線路尺寸,那麼這部分就會變得很難 - 我現在想不出一個簡單的解決方案(沒有太多的開銷)。 - Izzy
我現在所能提出的所有內容都涉及到獲取前n行,根據它們計算平均長度,並使用此值。這對你有幫助嗎? - Izzy


如果沒有找到執行此操作的命令,我寫了一個快速腳本(未經測試):

#!/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

0
2017-07-25 15:28





您可以使用linux命令sed從文件中刪除行。以下命令刪除filename.txt的最後一行:

sed '$d' filename.txt

使用awk或find,您可以搜索匹配sed命令的模式。首先使用awk進行搜索或找到要縮短的文件,然後使用sed刪除這些行。


-1
2017-07-24 07:06





我用尾巴做了類似的事。在這種情況下,僅保留最後10,000行:

TMP=$(tail -n 10000 /path/to/some/file 2>/dev/null) && echo "${TMP}" > /path/to/some/file

-1
2018-04-08 20:43