我有一个以 3x66 矩阵排列的文本文件mat.txt
,如下所示:
0 -1 0.000532 -0.00026 0.000465 etc...
0 0.000294 1 -0.000102 -0.1146 etc...
0 -0.000134 0.0000967 1 -0.9972 etc...
这些值可以被视为 3D 坐标对,其中每行的第一个值表示 (x,y,z) 坐标,每行的第二个值表示另一个 (x,y,z) 坐标,依此类推。除了开头的零之外,数字随文件而变化,因此我需要根据文本文件中的位置而不是字符串来定位。
我需要从文件中删除某些坐标,坐标取决于它是哪个文件。我想也许可以用来awk
分隔和删除整个列,但我不确定如何动态读取要删除的列。我有单独的文本文件,其中包含需要删除的列。
例如:
cat delete.txt
2 5 18 27 59
我可以使用 awk 来隔离和删除第 2、5、18 等列吗?
for i in $(cat delete.txt)
do
awk '{print $i}' | rm $i << mat.txt
done
答案1
如果infile
是:
0 -1 0.000532 -0.00026 0.000465 etc...
0 0.000294 1 -0.000102 -0.1146 etc...
0 -0.000134 0.0000967 1 -0.9972 etc...
delete
是您要从您的喜欢中删除它们的列号infile
:
2 4 6
与awk
,你可以这样做:
awk 'NR==FNR { split($0, to_delete); next }
# split 'delete' file into an array called to_delete on default FS (white-space)
{ for (col in to_delete) $to_delete[col]=""; print }' delete infile
# delete the columns from 'infile' that match with $column getting from array
这将为您提供从文件中删除第 2、4 和 6 列的输出。
0 0.000532 0.000465
0 1 -0.1146
0 0.0000967 -0.9972
答案2
听起来这就是您正在寻找的:
awk '
NR==FNR { split($0,del); next }
{
out = sep = ""
for (i=1; i<=NF; i++) {
if ( !(i in del) ) {
out = out sep $i
sep = OFS
}
}
print out
}
' delete.txt mat.txt
答案3
假设delete.txt只有一行,我们可以使用以下代码获取所需的列:
$ perl -psale '$. == 1 and
@indices2P = grep { my $c=$_+1; $d !~ /\b$c\b/ } 0 .. $#F;
$_ = "@F[@indices2P]";
' -- -d="$(< delete.txt)" mat.txt
结果:
0 0.000532 0.000465
0 1 -0.1146
0 0.0000967 -0.9972
解释:
将要删除的列存储在标量变量中$d
,并在读取文件的第一行mat.txt
计算需要打印的列索引。
然后在访问数组@F
进行打印时仅应用这些索引。
答案4
$ < delete.txt \
tr -s ' \t' '\n\n' | sort -nru |
sed -e 's|.*|s/\\s*\\S+//&|' |
sed -Ef - mat.txt
结果:
0 0.000532 0.000465
0 1 -0.1146
0 0.0000967 -0.9972
解释:
使用打开扩展正则表达式模式的 GNU sed,我们首先生成一个 sed 代码,当应用于 mat.txt 文件时,我们会得到我们喜欢的输出。
假设:
o The file delete.txt comprises only positive integers and max value < 512