如何使用 sed 从文本文件中删除多个随机行?

Ama*_*nda 4 sed

我想从一个有 90 行的文本文件中删除 10 条随机行,然后将其输出到一个新文件中。我一直在尝试使用 sed 来做到这一点,但我有两个问题。我正在使用:

sed -i $((1 + RANDOM & 90))d input.txt > output.txt
Run Code Online (Sandbox Code Playgroud)

然后运行命令 10 次(我认为有更好的方法来做到这一点!)

我遇到的第一个问题是我收到错误:

sed: -e 表达式 #1, char 2: 行地址 0 的无效使用

我认为这与它可能已经删除了第 1 行并再次尝试有关。

第二个问题是有时输出文件没有写入任何内容,即使它在使用相同命令之前工作。

cho*_*oba 8

您可能想使用RANDOM % 90而不是&. 这就是零的来源(删除第 1 行是可以的,在下一次运行中,这些行将被编号为 1 .. 89)。

但是有一个问题:公式可以多次生成相同的数字。为防止这种情况,请使用不同的方法:将数字随机排列并选择前十个:

shuf -i1-90 -n10 | sed 's/$/d/' | sed -f- input > output
Run Code Online (Sandbox Code Playgroud)

如果您不喜欢sed生成sed脚本,也可以使用printf

sed -f <( printf %dd\;  $(shuf -i1-90 -n10) ) input > output
Run Code Online (Sandbox Code Playgroud)

  • @choroba,改进,用`$(wc -l &lt;​​input)`替换`90` (3认同)
  • @don_crissti,我认为 OP 不想打乱整个文件并删除 n 行,只需从文件中删除 n 随机行。 (2认同)

Sté*_*las 5

如果您没有 GNU shuf,可移植地,您可以这样做:

awk -v n=90 -v p=10 '
  BEGIN {srand()}
  rand() * n-- < p {p--; next}
  {print}' < file
Run Code Online (Sandbox Code Playgroud)

它也将比具有高值的 shuf+sed 方法更有效,p因为它在 o(n) 中,而 shuf+sed 在 o(n*p) 中。当 n=1000000 时,我的系统上的断点在 GNU sed 与 GNU awk 的 p=35 以及 GNU sed 与 mawk 的 p=1 左右(因为在 mawk 中总是更快)。