コンマ区切りリストの最後のエントリを変更する


8

次のような巨大なテキストファイルがあります。

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,3
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,8
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,12

望ましい出力はこれです:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

ここや他のコミュニティで他の関連する投稿を試しましたが、私が望むものを正確に得ることができませんでした。

更新

これは、興味深い答えがある質問(Unix / perlとバッチ/ powershellの両方のソリューションが必要でした)です。

回答:


14

sprintf関数を使用した awkアプローチ(先行ゼロを追加するため):

awk -F, -v OFS=',' '$8=sprintf("MI-%02d",$8);' file

出力:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

-F,- ,フィールド区切り文字としてカンマを設定します

$8 -8番目のフィールドを指します

%02d-関数の引数を2桁の数値として扱う形式


レコードの最後のフィールドはによって提示できることに注意してください$NF

NFは事前定義された変数で、その値は現在のレコードのフィールド数です

したがって、(入力用)$NFと同じです$8

awk -F, -v OFS=',' '$(NF)=sprintf("MI-%02d", $(NF))' file

1
警告の言葉(この例では関係ありませんが、他の場合にも当てはまる可能性があります):フィールドの1つ(ここでは$ 8)の値を変更すると、行全体のフィールドが "再計算"され、副次的な影響があります:ex1:複数の区切り文字が失われます「:echoが"1   2 3    4" | awk '{$2=$2;print $0}'得られます1 2 3 4(のみ1スペース(またはOFS)フィールド間左)。ex2)echo "1,,,2,3,,,,4" | awk -F',' '{$2=$2;print $0}'は:(1   2 3    4カンマがスペースになりました)を与えます。他の副作用があるかもしれません。フィールドをサポートすることで有害な副作用が発生する場合は、テストして別のアプローチ(例:$ 0のコピー変数のgsub)を使用します。
Olivier Dulac 2017

3

次を使用して試すことができますawk

awk 'BEGIN { FS = OFS = "," } { $NF = sprintf("MI-%02d", $NF); } 1' file

2

これがperlソリューションです:

$ perl -F',' -lane '$last=$#F;$F[$last]=sprintf("MI-%02d",$F[$last]);print join ",", @F' input.txt                                       
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

-aフラグで指定されたセパレータに基づいて、アレイとして扱う入力に私たちを可能にします-F。基本的には、その配列の最後の項目を変更し、joinコマンドで再構築します。


お返事ありがとうございます。誰かがperlを必要とする場合に役立ちますが、それでもsprintfあなたの答えの中核となる考えです。それが正しくないのではなく、受け入れられた回答とは異なる何かを提供しないだけです。とにかく+1。
M-2017

1
@Masoudまあ、ここでの主な理由は、sprintf()通常、特定の形式の文字列を変数に書き込むときに使用されるため、他の多くの言語で使用されているためです。私はそれをPythonでも書くことができます-Pythonにはありませんsprintf()が、コアとなる考え方は同じです-フォーマットされた文字列を変数に書き込みます。または、配列アイテムを直接操作して、それらを出力することもできます。このタイプの質問では、有限の量の解決策があります。基本的には、私が言おうとしていることです
Sergiy Kolodyazhnyy

1

次のような入力データの場合:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,3  
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,8  
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,14  
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,12  

text.csv

以下のコード

awk -F"," '{ i = 0;
  MyOutLine = "";
  j = NF - 1;
  while ( i < j ) {
    i++;
    MyOutLine = MyOutLine""$i",";
  }
  i++;
  x = sprintf( "%.2i", $i );
  y = "MI-"x;
  MyOutLine = MyOutLine""y;
  print MyOutLine; }' ./text.csv  

次のような出力を生成します:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

1

Tcl

これがinput.csvファイルから読み込んで結果をoutput.csvファイルに入れるTclを使用して行われた私の解決策です

set in [open input.csv]
set out [open output.csv w]

while {![eof $in]} {
   set line [gets $in]
   set last_comma_pos [string last , $line]
   puts $out [string range $line 0 $last_comma_pos][format MI-%02d [string range $line $last_comma_pos+1 end]]
}

close $in
close $out

デモンストレーション

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.