最初と5番目の列を取得するために、次のデータを処理しています。形式を形式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
その後、意味のない数の行を削除するために一度に1つずつ試しましたが、次のコマンドで失敗しました。
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は、有理数と組み込みのUnicodeサポートを備えたPerlファミリのプログラミング言語です。上記の一般的な戦略は、1列と5列(インデックス)の値が測定値DEG
の合計になるハッシュ配列を作成することです。key
[0,4]
value
@
- 署名されたarray()が宣言されました@a
。 Rakuコードは自動的にそれを読み、lines
改行join
文字に戻します\n
。ここから以前に発生した改行文字をsplit
見つけて記録を破ります。ブロックを入力すると、各レコードが再ラップされ、最初の要素の3番目の単語がになります。太い矢印は、「ペア」構造を表します。これら2つの呼び出しに注意してください。数字の後の最初の呼び出しとプラス記号を使用または挿入します。マイナス記号で構成されるカスタム文字クラスの間に「e」があり、2番目の呼び出しは「D」を「e」に変更します。値が変換され、ハッシュ値が配列にプッシュされます。このメソッドは、Rakuデータの内部表現を視覚化するために出力行に追加されます(ノートは同義語として使用することもできます)。\n
DEG
{ … }
split
\n
.[0].words.[2]
key
=>
value
.subst
\d
<[+-]>
.Num
%( … )
@a
.raku
.perl
プロットの実際の出力:
.raku.put for @a
希望のプロット出力を取得するには、最後の行を変更してください。以下はいくつかの例です(必要に応じてRakuprintf
または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
このラインを出力するかどうかによって異なります。