Awk

將兩個不同模式之間的數字相乘並列印整個文件

  • July 9, 2021

我想用相乘的數字替換模式之間的數字並列印所有行。該文件是 newick 格式的樹文件,僅包含一行。我的目標是)之前和之後的所有數字:。我想將兩個符號之間的所有數字乘以 100。

文件:

((((A_8:0.000846,(A_5:0.002449,(A_1:1e-06,((A_4:1e-06,((A_7:1e-06,A_6:0.001061)0.714000:1e-06,A_3:1e-06)0.314500:1e-06)0.358667:1e-06,A_2:1e-06)0.361000:1e-06)0.434800:1e-06)0.683500:0.001619)0.888571:0.001931,A_9:0.00069)0.688471:0.000691,...

對我來說,最簡單的方法似乎是通過首先用新行替換所有“:”符號來拆分文件。所以我所有的目標數字現在都在單獨的行中,並出現在). 然後,我使用下面的 awk 腳本將目標數字乘以 100,但沒有設法保留沒有目標數字的行。

腳本:

sed 's/:/\n/g' df9.tree | awk -F")" '{OFS=")"} $2=$2*100 {print $0}'
sed 's/:/\n/g' df9.tree | awk '$NF ~/)/ {$NF *=100}1'

在這種情況下,如何將數字相乘)並列印整個文件?還是有其他更簡單的方法可以直接查找介於:and之間的數字),將它們乘以 100 並列印整個文件?

更新:預期輸出

((((A_8:0.000846,(A_5:0.002449,(A_1:1e-06,((A_4:1e-06,((A_7:1e-06,A_6:0.001061)71.4000:1e-06,A_3:1e-06)31.4500:1e-06)35.8667:1e-06,A_2:1e-06)36.1000:1e-06)43.4800:1e-06)68.3500:0.001619)88.8571:0.001931,A_9:0.00069)68.8471:0.000691,...)
$ perl -pe 's/\)([-0-9.]+):/sprintf ")%.4f:", $1 * 100/eg' df9.tree
((((A_8:0.000846,(A_5:0.002449,(A_1:1e-06,((A:1e-06,((A_7:1e-06,A:0.001061)71.4000:1e-06,A:1e-06)31.4500:1e-06)35.8667:1e-06,A:1e-06)36.1000:1e-06)43.4800:1e-06)68.3500:0.001619)88.8571:0.001931,A:0.00069)68.8471:0.000691,...

替換緊跟一個)字元並:以數字乘以 100 的字元結​​尾的所有數字(定義為一個或多個數字、句點或減號的序列)。

例如)0.714000:更改為)71.4000:

它使用 perl 的/e正則表達式求值修飾符在運算符的 RHS 中執行 perl 程式碼s///。查看man perlop並蒐索s\/PATTERN詳細資訊。sprintf用於將數字格式化為小數點後 4 位。


如果和之間的數字)可以:是簡單的十進製表示法(“0.714000”)或“C float”風格的科學記數法(“1e-06”),則正則表達式需要稍微複雜一點才能匹配所有可能的變化:

$ perl -pe 's/\)(([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?):/sprintf ")%.4f:", $1 * 100/eg' df9.tree
((((A_8:0.000846,(A_5:0.002449,(A_1:1e-06,((A_4:1e-06,((A_7:1e-06,A_6:0.001061)71.4000:1e-06,A_3:1e-06)31.4500:1e-06)35.8667:1e-06,A_2:1e-06)36.1000:1e-06)43.4800:1e-06)68.3500:0.001619)88.8571:0.001931,A_9:0.00069)68.8471:0.000691,...)

以下也可能有效,但可能有一些數字不匹配:

perl -pe 's/\)([-0-9.eE+]+):/sprintf ")%.4f:", $1 * 100/eg'
awk 'BEGIN {OFS=FS=":"; ORS=RS=")"} NR>1 {$1=sprintf("%.4f", $1 * 100)}1' df9.tree

如果您接受將 RS 記錄和 FS 欄位分開,則所需的編號將始終位於第一條記錄之後的第一個欄位中。

引用自:https://unix.stackexchange.com/questions/657496