【发布时间】:2023-03-05 00:26:01
【问题描述】:
我见过很多变种,很困惑如何解决这三个问题。
- 从文件中删除除第一行之外的所有行
- 从文件中删除带有行号的行
- 从具有一系列行号的文件中删除行
【问题讨论】:
我见过很多变种,很困惑如何解决这三个问题。
【问题讨论】:
使用 sed:
删除第一行:
sed '1d' file-name
删除第 10 行:
sed '10d' file-name
删除第 5 行到第 10 行
sed '5,10d' file-name
以上所有 sed 命令都会在标准输出上写入输出,您可以根据需要重定向到另一个文件,或者使用 sed 的 -i 标志来内联编辑文件。
【讨论】:
sed '2,$d' filename,或sed '1!d' filename,或sed -n '1p' filename。
Print first line only 与 delete all lines but the first 相同,这就是为什么 sed -n '1p' 也是正确的。
使用 awk:
# delete line 1
awk 'NR == 1 {next} {print}' file
# delete line number stored in shell variable $n
awk -v n=$n 'NR == n {next} {print}' file
# delete between lines $a and $b inclusive
awk -v m=$a -v n=$b 'm <= NR && NR <= n {next} {print}' file
为了节省一些字符,{print} 可以替换为 1
要覆盖原始文件,你必须这样做
awk '...' file > tmpfile && mv tmpfile file
【讨论】:
如果你的系统有 bash,你就可以使用它。背后的基本思想是设置一个计数并在迭代文件时增加该计数。
1) 从文件中删除除第一行之外的所有行
read -r line < file; echo "$line" > temp && mv temp file
2) 从文件中删除行号为一行
declare -i count=0
while read -r line
do
((count++))
case "$count" in
10) continue;;
* ) echo "$line";;
esac
done < file > temp && mv temp file
3) 从文件中删除行号范围为 10 到 20 的行
declare -i count=0
while read -r line
do
((count++))
if (( $c < 10 && $c > 20 ));then
echo "$line";;
fi
done < file > temp && mv temp file
【讨论】:
read -r 仍然会去除前导和尾随空格。你需要做IFS= read -r line。此外请注意,从 shell 脚本中,此方法对于小文件更快,因为它避免了分叉,但对于大文件则较慢,因为 read 本质上效率低下,通常一次读取一个字节,或者每次调用一次读取和 lseek 调用,并且bash 中的字符串处理往往效率低下(在其他 shell 中效率较低)。
read 对带有bash 的大文件效率低下。如果 OP 的文件很大并且性能有问题,那么使用更好的工具。