我有大量的txt文件。每个txt文件的格式与此类似
200 0.2 0.1 0.5 0.4
500 0.4 0.9 0.9 0.1
我试图删除每个 txt 文件中第一个字段值大于 400 的每一行。因此上面的文件现在应该只包含以下内容:
200 0.2 0.1 0.5 0.4
代码
for file in *.txt; do
echo "$(awk '{ if ($1 < 401) print }' *.txt)" > tmp && mv tmp *.txt
done
rm -f tmp
但这不起作用,因为它将所有文件移动到下一个文本文件。
答案1
如果您使用 GNU awk(如果您使用 Linux,则几乎肯定是这样),您可以使用 GNU awk 的就地编辑库,甚至不需要 shellfor
循环或任何临时文件来完成此操作。
awk -i inplace '$1 < 401' ./*.txt
这将从每个文本文件中删除字段 1 > 400 的所有行。它的工作原理是首先加载 GNU awk 的inplace
库,然后仅输出$1 < 401
计算结果为 true 的行。
如果您希望 awk 在更改每个原始文件(例如带有 .bak 文件扩展名)之前对其进行备份,您可以使用 awk 的 INPLACE_SUFFIX 变量:
awk -i inplace -v INPLACE_SUFFIX=.bak '$1 < 401' ./*.txt
注意:与其他具有就地编辑选项的程序(例如sed
和perl
)不同, GNU awk 的选项是...ie 的缩写,即包含下一个参数中指定的 gawk 库。这个库(称为“inplace”)提供了就地编辑功能。-i
-i
--include
答案2
file
您需要在循环中引用;也没有必要使用echo
:
for file in *.txt; do
awk '{ if ($1 < 401) print }' < "$file" > tmp && mv -- tmp "$file"
done
rm -f tmp
AWK 代码也可以简化:
for file in *.txt; do
awk '$1 < 401' < "$file" > tmp && mv -- tmp "$file"
done
rm -f tmp
为了完全满足您的要求,应该更改测试:
for file in *.txt; do
awk '!($1 > 400)' < "$file" > tmp && mv -- tmp "$file"
done
rm -f tmp
答案3
您可以像这样更改代码来完成这项工作:
for file in *.txt; do
awk '{ if ($1 < 401) print }' < "$file" > tmp && mv -- tmp "$file"
done
rm -f tmp
但是在覆盖原始文件时要小心,最好在不同的目录(类似的目录)中创建修改后的文件:mv tmp modified/$file
并且不要忘记在将文件复制到该目录之前创建该目录。
如果您将逻辑定义为“大于 400”,您if
应该是:($1 <= 400
数字可以是 400.1)