使用 sed 和 wc 递归删除一半的文件行

Remove half the lines of files recursively using sed and wc

我想知道是否有办法使用 wcsed.

删除文件的一半行

我能做到:

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

从文件末尾删除第 50 行。我也可以这样做:

wc -l myfile.txt

其中returns文件中的行数。

但我真正想做的是这样的:

wc -l myfile.txt | sed -i '{wc -l result}/2,$d' myfile.txt
  1. 如何告诉 sed 删除从 wc -l 结果除以 2 开始的行?
  2. 如何递归执行此操作?

我猜你很接近。只需使用带有算术扩展的命令替换来获取起始行的值:

startline="$(( $(wc -l <myfile.txt) / 2 ))"
sed -i "$startline"',$d' myfile.txt

或单线:

sed -i "$(( $(wc -l <myfile.txt) / 2 ))"',$d' myfile.txt

从某种意义上说,读取文件两次(或者,如 Kent 所说,一次半)是不可避免的。如果您只使用一个进程,可能 稍微 更有效率。

awk 'NR==FNR { total=FNR; next }
    FNR>total/2 { exit } 1' myfile.txt myfile.txt

用 Awk 递归地做这个有点痛苦。如果你有 GNU Awk,你可以使用 -t inline 选项,但当你读取同一个文件两次时我不确定它的语义。也许只是回退到一个临时输出文件。

find . -type f -exec sh -c "awk 'NR==FNR { total=FNR; next }
    FNR>total/2 { exit } 1' {} {} >tmp &&
  mv tmp {}" _ \;

你可以使用head命令:

head -n -"$(($(wc -l<file)/2))" file

awk 也是可以的,加上 exit 语句,它可能会更快:

awk -v t="$(wc -l <file)" 'NR>=t/2{exit}7' file

您可以通过awk/head ... > newFilecmd > tmp && mv tmp file获取文件进行"in-place"更改。