如何删除带有无意义格式数字的行?

如何删除带有无意义格式数字的行?

我正在处理以下数据以获得第一列和第五列,将格式转换DE格式并删除包含乱码的行,例如9.410-316.

DEG =      1.500
     2.600D+01     0.000D+00     0.000D+00     0.000D+00     0.000D+00
     2.700D+01     8.720-304     2.369-316     7.556-316     9.410-316
     4.300D+01     1.208D-83     4.156D-96     7.360D-96     6.984D-96
     1.590D+02     8.002D-07     6.555D-19     7.748D-19     7.376D-19
     1.600D+02     1.173D-06     9.669D-19     1.143D-18     1.089D-18
     1.610D+02     1.709D-06     1.417D-18     1.676D-18     1.596D+01
     1.620D+02     2.468D-06     2.058D-18     2.436D-18     2.320D-10
DEG =     18.500 
     2.700D+01     2.794-314     0.000D+00     0.000D+00     0.000D+00
     2.800D+01     4.352-285     1.224-297     3.685-297     4.412-297
     8.800D+01     1.371D-02     6.564D-15     7.852D-15     7.275D-15 

我的问题是确定要删除的数字格式。到目前为止,我已经尝试过

maxa=18.5
maxangle=$(printf "%.3f" $maxa)
if (( $(echo "$maxa < 10" | bc -l) )); then
  txt2search="DEG =      $maxangle"
  # 6 spaces between = and value if deg=>10, else only 5)
else
  txt2search="DEG =     $maxangle"
fi

line=$(grep -n "$txt2search" file  | cut -d : -f 1)

# Once the line number is read for the string, skip a few lines (4) and read next several lines(1000)
beginline=$((line + 4))
endline=$((line + 1002))
awk -v a="$beginline" -v b="$endline" 'NR==a, NR==b {print $1, $5}' fileinput > fileoutput
sed -i 's/D/E/g' fileoutput

然后,为了丢弃带有无意义数字的行,我尝试(一次一个)并使用以下命令失败了。

sed -ni '/E/p' fileoutput
sed -E '/(E)/!d' fileoutput > spec2.tempdata
sed '/E/!d' fileoutput > spec2.tempdata
awk '!/E/' fileoutput > spec2.tempdata

如何识别并删除带有此类无意义数字的行?版本是

  • sed(GNU sed)4.7
  • grep (GNU grep) 3.4
  • GNU Awk 5.0.1,API:2.0(GNU MPFR 4.0.2,GNU MP 6.2.0)

输出将是

2.600D+01     0.000D+00     0.000D+00     0.000D+00     0.000D+00
4.300D+01     1.208D-83     4.156D-96     7.360D-96     6.984D-96
1.590D+02     8.002D-07     6.555D-19     7.748D-19     7.376D-19
1.600D+02     1.173D-06     9.669D-19     1.143D-18     1.089D-18
1.610D+02     1.709D-06     1.417D-18     1.676D-18     1.596D+01
1.620D+02     2.468D-06     2.058D-18     2.436D-18     2.320D-10

编辑:我正在寻找的解决方案是(参见第一条评论)

grep -v '[0-9]-'

答案1

使用(以前称为 Perl_6)

~$  raku -e 'my @a; for lines.join("\n").split(/ \n <?before DEG> /) { @a.push: %(.split("\n").[0].words.[2] => \
             .split("\n")[1..*].map(*.words[0,4])>>.map(*.subst( / (\d+) (<[+-]>) /, {$0 ~ "e" ~ $1} ).subst(/D/, "e") )>>.Num) };  \
             .raku.put for @a;'  file

用于可视化目的的示例输出:

${"1.500" => $($(26e0, 0e0), $(27e0, 9.41e-316), $(43e0, 6.984e-96), $(159e0, 7.376e-19), $(160e0, 1.089e-18), $(161e0, 15.96e0), $(162e0, 2.32e-10))}
${"18.500" => $($(27e0, 0e0), $(28e0, 4.412e-297), $(88e0, 7.275e-15))}

Raku 是 Perl 家族中的一种编程语言,具有有理数和内置 Unicode 支持。上面,一般策略是创建一个哈希数组,第 1 列和第 5 列(索引)中的DEG值为和测量值。key[0,4]value

@声明了 -sigiled 数组 ( ) @a。 Raku 代码会自动读取linesjoin并在换行符上将它们重新组合在一起\n。从这里开始,我们通过split查找\n之前出现的换行符来打破记录DEG。进入该{ … }块,每个记录再次split\n行,.[0].words.[2]第一个元素的第三个单词变成key.粗=>箭头表示“对”结构,成为value.请注意这两个.subst调用:第一个调用在数字和由加号或减号\d组成的定制字符类之间插入“e”,第二个调用将“D”更改为“e”。<[+-]>值被转换为.Num,并将%( … )哈希值推送到@a数组中。该.raku方法被添加到输出行,以实现 Raku 数据内部表示的可视化(note.perl也可用作同义词)。



绘图的实际输出:

更改最后一行.raku.put for @a以获得所需的绘图输出。下面是一些示例(如果需要,您也可以使用 Rakuprintfsprintf):

1.替换put上面的 out 行以返回第一个DEG

for @a[0].kv -> $k,$v {put ([Z] $k xx $v.elems, $v).join: "\n"}

#Returns 3-columns:

1.500 26 0
1.500 27 9.41e-316
1.500 43 6.984e-96
1.500 159 7.376e-19
1.500 160 1.089e-18
1.500 161 15.96
1.500 162 2.32e-10

2.或者使用以下行立即返回整个 3 列表put

for @a { for ($_.kv) -> $k,$v {put ([Z] $k xx $v.elems, $v).join: "\n"}};

#Returns:

1.500 26 0
1.500 27 9.41e-316
1.500 43 6.984e-96
1.500 159 7.376e-19
1.500 160 1.089e-18
1.500 161 15.96
1.500 162 2.32e-10
18.500 27 0
18.500 28 4.412e-297
18.500 88 7.275e-15

3. 最后: Raku 有一个=~=“公差”运算符,可用于确定值是否约为。等于 0(默认为 1e-15,请参阅下面的链接)。把它们放在一起:

~$ raku -e 'my @a; for lines.join("\n").split(/ \n <?before DEG> /) { @a.push: %(.split("\n").[0].words.[2] => \
            .split("\n")[1..*].map(*.words[0,4])>>.map(*.subst( / (\d+) (<[+-]>) /, {$0 ~ "e" ~ $1} ).subst(/D/, "e") )>>.Num) };  \
            for @a {  for ($_.kv) -> $k,$v {put ([Z] $k xx $v.elems,  $v>>.map( -> $i { ($i =~= 0) ?? 0 !! $i } )).join: "\n"}};'  file
1.500 26 0
1.500 27 0
1.500 43 0
1.500 159 0
1.500 160 0
1.500 161 15.96
1.500 162 2.32e-10
18.500 27 0
18.500 28 0
18.500 88 7.275e-15

https://docs.raku.org/language/hashmap.html
https://docs.raku.org/language/5to6-nutshell.html#=%3E_Fat_comma
https://docs.raku.org/routine/=~=.html
https://raku.org

答案2

FWIW 以下是如何将输入中的 D 更改为 E,然后通过比较添加之前和之后的值来判断字段是否为数字0(数字将保留其值,非数字则不会)

$ awk 'NF>3{gsub(/D/,"E"); for (i=1; i<=NF; i++) if ($i != $i+0) print "not a number:", $i}' file
not a number: 8.720-304
not a number: 2.369-316
not a number: 7.556-316
not a number: 9.410-316
not a number: 2.794-314
not a number: 4.352-285
not a number: 1.224-297
not a number: 3.685-297
not a number: 4.412-297

因此打印仅包含数字的行将是:

$ awk 'NF>3{gsub(/D/,"E"); for (i=1; i<=NF; i++) if ($i != $i+0) next; print}' file
     2.600E+01     0.000E+00     0.000E+00     0.000E+00     0.000E+00
     4.300E+01     1.208E-83     4.156E-96     7.360E-96     6.984E-96
     1.590E+02     8.002E-07     6.555E-19     7.748E-19     7.376E-19
     1.600E+02     1.173E-06     9.669E-19     1.143E-18     1.089E-18
     1.610E+02     1.709E-06     1.417E-18     1.676E-18     1.596E+01
     1.620E+02     2.468E-06     2.058E-18     2.436E-18     2.320E-10
     8.800E+01     1.371E-02     6.564E-15     7.852E-15     7.275E-15

或者:

$ awk 'NF>3{gsub(/D/,"E"); for (i=1; i<=NF; i++) if ($i != $i+0) next} 1' file
DEG =      1.500
     2.600E+01     0.000E+00     0.000E+00     0.000E+00     0.000E+00
     4.300E+01     1.208E-83     4.156E-96     7.360E-96     6.984E-96
     1.590E+02     8.002E-07     6.555E-19     7.748E-19     7.376E-19
     1.600E+02     1.173E-06     9.669E-19     1.143E-18     1.089E-18
     1.610E+02     1.709E-06     1.417E-18     1.676E-18     1.596E+01
     1.620E+02     2.468E-06     2.058E-18     2.436E-18     2.320E-10
DEG =     18.500
     8.800E+01     1.371E-02     6.564E-15     7.852E-15     7.275E-15

取决于您是否想要DEG输出这些行。

相关内容