Pra*_*dam 7 command-line text-processing
我有一个包含 10000 行的文件,我想从中删除 5 个随机确定的行。我怎样才能做到这一点?
Byt*_*der 15
与需要每行处理整个文件一次才能删除的 for 循环相比,您可能可以更有效地解决它。
filename="/PATH/TO/FILE"
number=5
line_count="$(wc -l < "$filename")"
line_nums_to_delete="$(shuf -i "1-$line_count" -n "$number")"
sed_script="$(printf '%dd;' $line_nums_to_delete)"
sed -i.bak -e "$sed_script" "$filename"
Run Code Online (Sandbox Code Playgroud)
或者在一行中(在定义filename
和number
变量或手动替换它们之后):
sed -i.bak -e "$(printf '%dd;' $(shuf -i "1-$(wc -l < "$filename")" -n "$number"))" "$filename"
Run Code Online (Sandbox Code Playgroud)
该-i.bak
开关告诉sed
编辑/立即更换输入文件,但保留原始数据,命名为喜欢的输入文件的备份副本,但与.bak
附加到文件名。如果您不想复制它,只需编写-i
.
顺便说一句,您不必像我一样使用变量。您也可以直接用适当的值替换"$number"
和"$filename"
。为了清楚起见,我只是这样做了。
分解并解释命令的其余部分:
sed -e "SCRIPT" "$filename"
Run Code Online (Sandbox Code Playgroud)
sed
在filename
变量指定的文件上运行文本处理工具,应用作为SCRIPT
参数给出的指令。
我们SCRIPT
在它上面的行中动态生成,它们运行命令并将它们的输出分配给变量。这里我们使用这些命令:
wc -l < "$filename"
读入由filename
变量指定的文件并输出该文件包含的行数。
shuf -i "1-$line_count" -n "$number
返回由number
变量指定的数量在 1 到$line_count
(包括两个边界)范围内的唯一随机数。
shuf -i 1-6 -n 2
将模拟投掷两个常规六面骰子。printf '%dd;' ARGUMENTS
返回一个格式化的字符串,包含所有ARGUMENTS
(这次不引用以将每个随机数视为单独的参数)。格式字符串%dd;
将在剩余参数时重复,并将%d
替换为表示为十进制数的参数。
1 7 42
将导致输出1d;7d;42d;
。结果最终$sed_script
是我们的SCRIPT
for sed
。普通数字被视为地址,即应用操作的行号,输入文件的第一行从 1 开始。d
是删除指定行的命令,;
分隔多个sed
脚本命令。
总之,整个命令首先检查filename
变量中指定的输入文件并计算其行数。然后它生成number
许多在 1 到行数范围内的唯一随机数,并从中构建一个sed
脚本来删除每个提到的随机行。最后sed
在文件上运行该脚本,修改它。
您可以使用 for 循环获取随机数并使用 sed 命令删除该行。
for i in {0..5};
do sed -i "$((1 + RANDOM % 10000))d" filename;
done
Run Code Online (Sandbox Code Playgroud)
小智 5
类似于 Shivaditya 的答案,但没有循环,并且会从整个文件中删除行而不仅仅是前 10 行:
sed -i "$((1+RANDOM%10000))d;$((1+RANDOM%10000))d;$((1+RANDOM%10000))d;$((1+RANDOM%10000))d;$((1+RANDOM%10000))d" filename
Run Code Online (Sandbox Code Playgroud)
将选择 1 到 10000 之间的五个随机数,并在一次操作中删除这些行。