【问题标题】:Remove half the lines of files recursively using sed and wc使用 sed 和 wc 递归删除文件的一半行
【发布时间】:2019-12-10 13:21:38
【问题描述】:

我想知道是否有办法使用wcsed 删除文件的一半。

我可以这样做:

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

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

wc -l myfile.txt

返回文件中的行数。

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

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

【问题讨论】:

  • 使用d 删除行,r 命令用于从另一个文件追加文本...尝试sed -i $(( $(wc -l <myfile.txt)/2 + 1 ))',$d' myfile.txt(注意我也在使用+1)跨度>

标签: bash sed wc


【解决方案1】:

你可以使用head命令:

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

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

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

您可以通过awk/head ... &gt; newFilecmd &gt; tmp &amp;&amp; mv tmp file 获取文件以进行“就地”更改。

【讨论】:

    【解决方案2】:

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

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

    或单线:

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

    【讨论】:

    • 谢谢,它似乎可以工作,但是,如何递归地对目录层次结构中的每个文件执行此命令?
    • 我会做find directory -type f | xargs -d $'\n' -n1 sh -c 'sed -i "$(( $(wc -l &lt;"$1") / 2 )),\$d" "$1"' -- 或类似的事情。我建议研究topic separately。或者find directory -type f -exec sh -c 'sed "$(( $(wc -l &lt;"$1") / 2 )),\$d" "$1"' -- {} \;
    【解决方案3】:

    在某种意义上,读取文件两次(或者,如 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 {}" _ \;
    

    【讨论】:

    • 其实我们不需要读取文件2x,我们只需要1.5x
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多