空白がある場合は削除し、ない場合は無視してください。

空白がある場合は削除し、ない場合は無視してください。

プログラムの出力から.csvファイルを作成したいと思います。元の出力の一部をこのレベルにカスタマイズしました。

  36.343074719185125    -1.488697037254009     0.517768286726280  -1.488697037254009    48.906350248447872    -0.255764113311881   0.51776828
6726280    -0.255764113311881    31.687963239227631

これまで、私はこれらのコマンドを使用してきました。

tail -12 Q.out | head -3 | sed 's/^........//' | tr -d '\n' > q.txt

問題は、その間に特定の数のスペースがないことです。 4つの時もあり、3つの時もあります。それはすべてプログラムの出力に依存します。たとえば、最初の値が36.343の場合は2つのスペース、3.6の場合は3つのスペース、360.34の場合は1つのスペースの前に付けます。もっときれいにする方法はありませんか?

生データ


                   0                     1                     2        

    0     36.343074719185125    -1.488697037254009     0.517768286726280
    1     -1.488697037254009    48.906350248447872    -0.255764113311881
    2      0.517768286726280    -0.255764113311881    31.687963239227631

    alpha_(0.000) =      38.979129402287 a.u.
FCHKWriter: !WARNING! method 'CCSD'' renamed to label 'CC'.
FCHKWriter: Writing 0100-A_ccsd.fchk with label ' CC Density'.

    Psi4 stopped on: Tuesday, 12 October 2021 04:09PM
    Psi4 wall time for execution: 0:17:43.19

*** Psi4 exiting successfully. Buy a developer a beer!

予想される結果

36.343074719185125,-1.488697037254009,0.517768286726280,-1.488697037254009,48.906350248447872,-0.255764113311881,0.51776828
6726280,-0.255764113311881,31.687963239227631

Ubuntu 20.04を使用しています

答え1

関心のあるデータの3行が元のデータの行4、5、6で、これらすべての数字をカンマ区切りリストで1行に入力するとします。

次の式は、sed目的の行範囲内にないすべての行を削除し、数字のみを含む最初の列を削除します。このtrコマンドはこのデータを読み取り、データを1行に1つずつ数値リストに変換します。改行で区切られた数字は、カンマで区切られたリストに変換されますpaste

sed -e '4,6 !d' \
    -e 's/[[:blank:]]*[[:digit:]]*[[:blank:]]*//' file |
tr -s ' ' '\n' |
paste -s -d, -

trsed繰り返されるスペースを単一のカンマで置き換えることで、それらを削除できます。

sed -e '4,6 !d' \
    -e 's/[[:blank:]]*[[:digit:]]*[[:blank:]]*//' \
    -e 's/[[:blank:]]\{1,\}/,/g' file |
paste -s -d, -

答え2

スペースで区切られたデータを処理するのに非常に堪能です。 @theyのように興味のある3行が4,5,6行であるとしましょう。

awk -v OFS=, '4 <= NR && NR <= 6 {print $2,$3,$4}' Q.out

出力

36.343074719185125,-1.488697037254009,0.517768286726280
-1.488697037254009,48.906350248447872,-0.255764113311881
0.517768286726280,-0.255764113311881,31.687963239227631

その後、これを行にリンクするには、次のようにします。paste

awk -v OFS=, '4 <= NR && NR <= 6 {print $2,$3,$4}' Q.out | paste -sd,

データは次の場所にあります。最後ファイルの10〜12行目。私たちを見てみましょうキャンセルファイルを作成し、既知の行範囲からデータを抽出し、データを反転して結合します。

tac Q.out \
| awk -v OFS=, '10 <= NR && NR <= 12 {print $2,$3,$4}' \
| tac \
| paste -sd,
36.343074719185125,-1.488697037254009,0.517768286726280,-1.488697037254009,48.906350248447872,-0.255764113311881,0.517768286726280,-0.255764113311881,31.687963239227631

答え3

これを使用してawkデータファイルを処理できます。あなたの例を見ると、各行には4つのフィールドがあり、最初のフィールドは負ではなく整数であると仮定できるようです。

awk 'NF == 4 && $1 ~ /^[0-9]+$/ {printf "%s,%s,%s\n", $2, $3, $4}' Q.out

結果

36.343074719185125,-1.488697037254009,0.517768286726280
-1.488697037254009,48.906350248447872,-0.255764113311881
0.517768286726280,-0.255764113311881,31.687963239227631

すべてのデータを1行に表示したいというさまざまなコメントを見ました。これはあなたの質問に説明がありません、混乱した2行の不規則な出力がありますが、とにかく修正します。

ここで元のawkステートメントを変更して、後続のデータ行を最初の行に追加してから、末尾の改行文字を追加できます。

awk '
    NF == 4 && $1 ~ /^[0-9]+$/ {printf "%s%s,%s,%s", s, $2, $3, $4; s=","}
    END {print ""}
' Q.out

答え4

すべてのUnixシステムのすべてのシェルでawkを使用してCSVに変換したい入力に、次のような長さの不確実なブロックが複数あるとします。

$ cat tst.awk
BEGIN { OFS="," }
(NF==4) && sub(/^ +[0-9]+ +/,"") {
    $1 = $1
    rec = (rec == "" ? "" : rec OFS) $0
}
!NF && (rec != "") {
    print rec
    rec = ""
}

$ awk -f tst.awk file
36.343074719185125,-1.488697037254009,0.517768286726280,-1.488697037254009,48.906350248447872,-0.255764113311881,0.517768286726280,-0.255764113311881,31.687963239227631

関連情報