文件中的数字选择,只保留那些以linux中的数字开头的行

时间:2015-03-15 19:35:28

标签: linux awk sed

我的文件格式如下。请注意,这些条目是空格分开的。

16402       8    3858    3877    3098    3099
3858  -9.0743538e+01   1.5161710e+02  -5.4964638e+00
3244  -9.7903877e+01   1.8551400e-13   1.0194137e+01
3877  -9.2467590e+01   1.5160857e+02  -5.4969416e+00
4330  -9.3877419e+01   8.8259323e+01  -5.4966841e+00
3098  -9.2476135e+01   1.5336685e+02  -5.4963140e+00
5431  -6.1601208e+01   3.3540974e+01   1.0309820e+01
3099  -9.0752136e+01   1.5337535e+02  -5.4963264e+00
3600  -6.3099121e+01   1.3944173e+02  -5.4964156e+00
5418  -6.6785469e+01   2.9993099e+01   1.0291004e+01

有6个条目的行,有4个条目的文件。总共6个条目的行最后4个条目作为节点号,具有4个条目的行是具有空间坐标的那些节点号。我想只保留4个输入行中6个数字行中列出的节点,并删除所有其他节点,以便我的文件看起来像

16402       8    3858    3877    3098    3099
3858  -9.0743538e+01   1.5161710e+02  -5.4964638e+00
3877  -9.2467590e+01   1.5160857e+02  -5.4969416e+00
3098  -9.2476135e+01   1.5336685e+02  -5.4963140e+00
3099  -9.0752136e+01   1.5337535e+02  -5.4963264e+00

此文件已经创建了一些数据处理,因此保持格式很重要。我在文件中有数千行,6位数字条目和4位数字条目,因此一般解决方案对我学习和应用于其他案例也很有帮助。有关于sed或awk的任何建议吗?

感谢

3 个答案:

答案 0 :(得分:0)

您可以使用以下awk脚本:

awk 'NF==6{print;b=b" "$3" "$4" "$5" "$6}NF==4{if(b ~ "\\y"$1"\\y") print}' input.txt

说明:

该命令管理一个缓冲区,该缓冲区包含六列的所有最后4个字段。该变量称为b。每次awk输入包含六列的行时,都会打印该行并将其附加到b

如果输入包含4列的行awk,请使用函数b检查$1是否包含第一个字段match()的值。

输出:

16402       8    3858    3877    3098    3099
3858  -9.0743538e+01   1.5161710e+02  -5.4964638e+00
3877  -9.2467590e+01   1.5160857e+02  -5.4969416e+00
3098  -9.2476135e+01   1.5336685e+02  -5.4963140e+00
3099  -9.0752136e+01   1.5337535e+02  -5.4963264e+00

注意,如果安全的是,具有6列的行仅适用于具有4列的以下行,直到出现具有6列的新行,则该命令可以更改为:

awk 'NF==6{print;b=b" "$3" "$4" "$5" "$6}NF==4{if(b ~ "\\y"$1"\\y") print}' input.txt

由于最大缓冲区大小只有一行,因此性能会好很多。

答案 1 :(得分:0)

我会将4个数字存储在一个数组中,然后测试数组中是否存在$ 1。

awk '
    NF == 6 {
        delete n
        for (i=3; i<=NF; i++)
            n[$i]=1
        print
        next
    } 
    $1 in n
' file

答案 2 :(得分:0)

如果6场线始终出现在他们选择的4场线之前,那么

awk 'NF == 6 { for(i = 3; i <= 6; ++i) a[$i]; print } NF == 4 && $1 in a' filename

会奏效。具体如下:

NF == 6 {                         # in a six-field line:
  for(i = 3; i <= 6; ++i) a[$i]   # remember the relevant fields
  print
}
NF == 4 && $1 in a                # and subsequently select four-field lines
                                  # by them

否则,您需要对文件进行第二次传递,并处理第二遍中第一个和第四个字段行中的六个字段行:

awk 'NR == FNR && NF == 6 { for(i = 3; i <= 6; ++i) a[$i]; print } FNR != NR && NF == 4 && $1 in a' filename filename