
この入力があります。
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