의미 없는 형식의 숫자가 있는 행을 삭제하는 방법은 무엇입니까?

의미 없는 형식의 숫자가 있는 행을 삭제하는 방법은 무엇입니까?

첫 번째와 다섯 번째 열을 얻기 위해 다음 데이터를 처리 중입니다. 형식을 형식 D으로 변환 E하고 횡설수설이 포함된 행을 제거합니다 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 제품군의 프로그래밍 언어입니다. 위에서 일반적인 전략은 1열과 5열(인덱스)의 값이 DEG측정된 값의 합이 되는 해시 배열을 만드는 것입니다.key[0,4]value

@- 서명된 array()가 선언되었습니다 @a. Raku 코드는 자동으로 이를 읽고 lines개행 join문자에 다시 합칩니다 \n. 여기서부터 이전에 발생한 개행 문자를 split찾아 기록을 깨뜨립니다 . 블록 을 입력하면 각 레코드가 다시 래핑 되고 첫 번째 요소의 세 번째 단어는 가 됩니다 . 두꺼운 화살표는 가 되는 "쌍" 구조를 나타냅니다 . 이 두 호출에 유의하세요. 숫자 뒤의 첫 번째 호출과 더하기 기호를 사용하거나 삽입합니다 . 빼기 기호로 구성된 사용자 정의 문자 클래스 사이에 "e"가 있고 두 번째 호출은 "D"를 "e"로 변경합니다. 값이 변환되고 해시 값이 배열로 푸시됩니다. 이 메서드는 Raku 데이터의 내부 표현을 시각화할 수 있도록 출력 행에 추가됩니다(노트는 동의어로 사용될 수도 있음).\nDEG{ … }split\n.[0].words.[2]key=>value.subst\d<[+-]>.Num%( … )@a.raku.perl



플롯의 실제 출력:

.raku.put for @a원하는 플롯 출력을 얻으려면 마지막 줄을 변경하십시오 . 다음은 몇 가지 예입니다(필요한 경우 Raku printf또는 Raku를 사용할 수도 있습니다 sprintf).

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

삼. 마침내: 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/언어/hashmap.html
https://docs.raku.org/언어/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이 라인을 출력 할지 여부에 따라 다릅니다 .

관련 정보