2番目のフィールドの重複値に基づいてフィールドレコードに文字を追加する

2番目のフィールドの重複値に基づいてフィールドレコードに文字を追加する

この入力があります。

array='2       0.00000         -1.45191
6       0.81778         -0.63413
10      0.85020         -0.60170
8       1.40260         -0.04931
22      3.25781         1.80590
20      4.32051         2.86860
6       0.00000         -0.93906
18      0.07618         -0.86288
8       0.36922         -0.56984
12      0.71195         -0.22711
16      0.88517         -0.05389'

同じ配列をコピーしようとしていますが、

2       0.00000         -1.45191
6       0.81778         -0.63413
10      0.85020         -0.60170
8       1.40260         -0.04931
22      3.25781         1.80590
20      4.32051         2.86860
6-      0.00000         -0.93906
18-     0.07618         -0.86288
8-      0.36922         -0.56984
12-     0.71195         -0.22711
16-     0.88517         -0.05389

違いは、$1最初のフィールドの2番目の部分0.00000には、2番目のフィールドの2番目の値をマーカーとして使用して接尾辞が付けられることです。$2このコマンドが利用可能であればawkうれしいです。

答え1

あなたの例に基づいて、現れる必要なのは、2番目の列に0.00000文字列(または数値)の発生回数を記録し、数が2に達したときに最初の列の値に追加することです。0-

printf '%s\n' "$array" | awk '$2 == "0.00000" {++ind} ind == 2 {$1 = $1"-"} 1'

ただし、これは条件を満たすレコードの列区切り文字をデフォルト(単一スペース)出力区切り文字に置き換えます。もし入力区切り文字は一連の空白文字なので、ソートを維持する1つの方法は、最初の空白文字を次のように置き換えることです-

$ printf '%s\n' "$array" | awk '$2 == "0.00000" {++ind} ind == 2 {sub(/ /,"-")} 1'
2       0.00000         -1.45191
6       0.81778         -0.63413
10      0.85020         -0.60170
8       1.40260         -0.04931
22      3.25781         1.80590
20      4.32051         2.86860
6-      0.00000         -0.93906
18-     0.07618         -0.86288
8-      0.36922         -0.56984
12-     0.71195         -0.22711
16-     0.88517         -0.05389

答え2

前の質問によると、タブで区切られた入力があるようです。以下を試してください。

$ printf '%s\n' "$array" | awk 'BEGIN{FS=OFS="\t"} ($2==0) && c++{s="-"} {$1=$1 s} 1'
2       0.00000 -1.45191
6       0.81778 -0.63413
10      0.85020 -0.60170
8       1.40260 -0.04931
22      3.25781 1.80590
20      4.32051 2.86860
6-      0.00000 -0.93906
18-     0.07618 -0.86288
8-      0.36922 -0.56984
12-     0.71195 -0.22711
16-     0.88517 -0.05389

また、上記は、0第3またはそれ以降の値が列2に発生した場合でも、-列1にsを追加すると仮定している。

答え3

awk次の方法で解決できます。

printf '%s\n' "$array" |
awk -F '\t' 'BEGIN{OFS=FS}
($2 ~ /^0\.0+$/ && ++k==2),0 {
  $1 = $1 "-"
}1' -
  • 私達は範囲演算子を使用します,
  • 範囲演算子は最初は false です。左のオペランドがtrueと評価されると、範囲はtrueになり、右のオペランドがtrueと評価されるまでtrueのままです。
  • 左のオペランドは$2 ~ /^0\.0+$/ && ++k==2
  • したがって、2 番目の列が浮動小数点 0 で、2 番目の列が発生した場合は true と評価されます。
  • その後、範囲演算子は、右側が真(私たちの場合は0)と評価されるまで真を保持するため、決して発生しません。
  • IOW、2番目の列のゼロを含む行からeofまでの範囲はtrueです。
  • 範囲内の操作には、最初のフィールドの後にダッシュが付いています。
  • 孤独1フィールドの1つに触れたため、再構成された$ 0はTAB(OFS)を使用してフィールドをリンクしてSTDOUTに印刷する必要があります。


GNU sed-E正規表現の作成を簡素化するには、拡張正規表現モード()を使用します。

printf '%s\n' "$array" |
sed -E '
  0,/^[^\t]+\t+0\.0+(\t|$)/b
  //,$s/\t/-&/
' -

  • /^[^\t]+\t+0\.0+(\t|$)/2番目のフィールドが0の行を選択する正規表現です。
  • 最初の範囲は、行番号0から2番目の列で最初に表示される0までの行を選択します。これらの行はすべて変更されずにSTDOUTに渡されます。
  • 次回、2 番目には 2 番目の列から eof までゼロが表示されます。ここでは、最初の空白文字をダッシュ​​に変更します。これは、行に先行スペースがないと仮定します。
  • これら2つの範囲に属さない他の行は、変更されずにSTDOUTに渡されます。
  • ゼロ行番号は、正規表現が最初の行と一致する場合を処理するためのGNU sed拡張です。

出力:

2   0.00000 -1.45191
6   0.81778 -0.63413
10  0.85020 -0.60170
8   1.40260 -0.04931
22  3.25781 1.80590
20  4.32051 2.86860
6-  0.00000 -0.93906
18- 0.07618 -0.86288
8-  0.36922 -0.56984
12- 0.71195 -0.22711
16- 0.88517 -0.05389

関連情報