我有大量文件,其中一些文件很长。如果文件较大,我想通过删除文件末尾来将它们截断为一定大小。但我只想删除整行。我该怎么做?这感觉像是 Linux 工具链可以处理的事情,但我不知道正确的命令。
例如,假设我有一个 120,000 字节的文件,每行 300 字节,我想将其截断为 10,000 字节。前 33 行应保留(9900 字节),其余部分应被截断。我不想在 10,000 字节处截断,因为那样会留下部分行。
当然,文件的长度是不同的,并且行的长度也不都是相同的。
理想情况下,生成的文件会稍微短一些而不是稍微长一些(如果断点在一条长线上),但这并不重要,如果这样更容易,文件可以稍微长一些。我希望直接对文件进行更改(好吧,可能是将新文件复制到其他地方,删除原始文件,然后移动新文件,但从用户的角度来看,这是一样的)。将数据重定向到一堆地方然后再返回的解决方案可能会损坏文件,我想避免这种情况……
答案1
如果使用sed
/ ,wc
则可以避免前面答案中的复杂性。使用 OP 提供的示例(显示awk
完全的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
上述答案假设:
- 文本文件使用 Unix 行终止符 (
\n
)。对于 Dos/Windows 文本文件 (\r\n
),请更改length() + 1
为length() + 2
- 文本文件只包含单字节字符。如果有多字节字符(例如在 unicode 环境下),请设置环境
LC_CTYPE=C
以强制在字节级别进行解释。
答案2
这种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))
至少在使用 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
。但为了提高灵活性,在某些 shell 脚本中可以使用变量。
对于基于文件大小的条件处理,可以使用以下“测试”构造:
[ "$(ls -lk $file | awk ' {print $5}')" -gt 100 ] &&
意思是:“如果大小$file
超过 100kB,则执行...”(ls -lk
在位置 5 处列出文件大小(以 kB 为单位),因此awk
用于准确提取此大小)。
答案3
您可以使用 Linux 命令 sed 从文件中删除行。以下命令删除 filename.txt 的最后一行:
sed '$d' filename.txt
使用 awk 或 find,您可以搜索与 sed 命令匹配的模式。首先,使用 awk 或 find 搜索要缩短的文件,然后使用 sed 删除行。
答案4
我对 tail 做了类似的事情。在这种情况下,只保留最后 10,000 行:
TMP=$(tail -n 10000 /path/to/some/file 2>/dev/null) && echo "${TMP}" > /path/to/some/file