私はUbuntu 14.04.1 LTS 64ビットを実行しており、次の出力生成というプログラムがBash 4.3.11(1)-release
あります。harminv
$ h5totxt hsli0.126.h5 | harminv -vt 0.1 -w 2-3 -a 0.9 -f 200
# harminv: 1902 inputs, dt = 0.1
frequency, decay constant, Q, amplitude, phase, error
# searching frequency range 0.31831 - 0.477465
# using 200 spectral basis functions, density 6.60692
-2.14026, 3.511909e-05, 30471.5, 0.922444, 1.26783, 1.383955e-06
2.14013, 2.052504e-05, 52134.7, 0.920264, -1.27977, 3.426846e-07
# harminv: 2/6 modes are ok: errs <= 1.000000e-01 and inf * 3.426846e-07
, amps >= 0, 9.000000e-01 * 0.922444, |Q| >= 10
-v
(verbose)オプションを省略すると、次のようにより簡潔な出力が得られます。
$ h5totxt hsli0.126.h5 | harminv -t 0.1 -w 2-3 -a 0.9 -f 200
frequency, decay constant, Q, amplitude, phase, error
-2.14026, 3.511909e-05, 30471.5, 0.922444, 1.26783, 1.383955e-06
2.14013, 2.052504e-05, 52134.7, 0.920264, -1.27977, 3.426846e-07
どちらの場合も、出力の最初の列から正の数を抽出できるようにしたいのですが、これを行う方法がわかりません。またはを使用できsed
ますawk
。誰かが私に正しい方向を教えてくれれば幸いです。私の目標は、すべての正数を記録して他の変数についてプロットすることです。
答え1
sedを使う
これにより、正数で始まる行だけが印刷されます。
sed -n 's/^\([[:digit:]][^ ,]*\).*/\1/p'
パイプラインの1つと組み合わせると、次のようになります。
h5totxt hsli0.126.h5 | harminv -vt 0.1 -w 2-3 -a 0.9 -f 200 | sed -n 's/^\([[:digit:]][^ ,]*\).*/\1/p'
どのように動作しますか?
-n
これは
sed
、明示的に要求しない限り、どの行も印刷しないように指示します。s/^\([[:digit:]][^ ,]*\).*/\1/p
これは
sed
、正の数で始まる行を見つけて、その数だけを印刷することを意味します。正規表現では、
^
行の先頭のみが一致します。[[:digit:]]
すべての数字と一致します。[^ ,]*
数字の後のすべての項目と一致します(スペースやカンマを除く)。後でその番号を呼び出すために括弧でグループ化されています\1
。その後、行全体が数字に変わり、オプションで印刷するように指示p
します。sed
数字と一致するものです
[0-9]
。 Unicodeフォントの出現により、これは信頼できなくなります。[[:digit:]]
しかし、式はUnicodeから安全です。
拡張正規表現の使用の代替
すべてのLinuxシステムの場合と同様に、GNU sedを使用している場合は、この-r
オプションを使用して次のようにすることができます。拡張正規表現。拡張正規表現では、グループ化に使用される角かっこをエスケープする必要はありません。
sed -rn 's/^([[:digit:]][^ ,]*).*/\1/p'
OSXや他のBSDシステムでは、-E
代わりに-r
。
awkを使う
同じことを行いますが、以下を使用してくださいawk
。
awk -F, '/^[[:digit:]]/{print $1}'
パイプラインと組み合わせる:
h5totxt hsli0.126.h5 | harminv -vt 0.1 -w 2-3 -a 0.9 -f 200 | awk -F, '/^[[:digit:]]/{print $1}'
答え2
表示された入力を考慮すると、次のことが機能します。
sed -n 's/[^[:digit:]]/\
&/;/.\n/P'
...または...
sed 's/[^[:digit:]].*//;/./!d'
...sed
場合によってはこれを書くことができます...
sed -n 's/[^0-9]/\n&/;/.\n/P'
...または...
sed 's/[^0-9].*//;/./!d'
...おそらく - 入力データセットに応じて - GNUを使用してsed
、たとえば...
sed -n 's/\W/\n&/;/.\n/P'
...または...
sed 's/\W.*//;/./!d'
正規言語は基本的に補完の説明なので、ほぼ常に正規表現を完全に変更できます。時にはこれは作業量を減らします。
したがって、文字列の頭部で長さが不明な特定のパターンを検索する場合は、パターンと一致しない文字列の最初の部分を見つけるのがより簡単になる可能性があります。
上記の最初の例では、\n
行に最初に表示される数字以外の文字の前に改行文字を挿入します。次に、機能していることを確認します。(こうすれば)、挿入された内容と行の先頭との間に少なくとも1文字。それ以外の場合は印刷せず、そうであれば\n
挿入された行にのみ印刷します。
次の例は似ています。パターンと一致しない文字で始まる行から最も長い文字列を削除し、出力からすべての空白行を削除します。
残りは、一部が解釈できるものと同じ作業をさらに実行するための略語ですsed
。しかし、最初の2つはPOSIX sed
構文仕様に非常に厳密に準拠しています。[[:digit:]]
(UTF-8がASCIIの上位セットであり、アラビア数字を含まないほとんどの言語がこのコードを記述する言語と非常に異なることを理解しているため、これは少し過剰になる可能性があります。とにかく機能するには追加の修正が必要です。。
すべての例(実装とコメントの入力によって異なります)は、行の先頭から始まり、最初に一致する連続した数字のシーケンスのみを印刷する必要があります。
それでも考えてみると空白とカンマで区切るようですので、次のように書くこともできそうです。
sed -n 'y/, -/\n\n\n/;/^[0-9]/P'
...実際の正規表現の一致はほとんどありません -y///
関数として翻訳するパターンでグループ化する代わりに文字を使用してください。正規表現マッチングは結果テストにのみ使用されます。