ファイルの最初の列をコマンド出力に置き換える

ファイルの最初の列をコマンド出力に置き換える

この質問からUnixを使用した列のコピーと置換

このファイルでのみ機能するソリューションを構築しようとしています。

20070101 10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
20070102 10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
20070103 10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
20070104 10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

出力を取得します。

01/01/2007  10.2317   79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007  10.2317   79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007  10.2317   79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007  10.2317   79.1638   8.1  26.0  19.6   0.0  15.5  94.1

その他の書類は関係ありません。

だから最初の列を変換された日付に置き換えたいのです。

元のファイルから日付を取得しました。

$ awk '{print $1}' filedate.txt
20070101
20070102
20070103
20070104

その後、以下を使用して日付変換を実行しました。

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done
01/01/2007
02/01/2007
03/01/2007
04/01/2007

ただし、変換された日付値でファイルの最初の列を変更することはできません。私はawk代替()を使ってみましたawk '{$1=$dt}1'

for i in $(awk '{print $1}' filedate.txt); do dt=$(date -d "$i" +%d/%m/%Y) && awk '{$1=$dt}1' filedate.txt; done

ただし、ループが含まれているため、出力は必要に応じて出ません。

どうすればいいですかawk?で同じことができますかsed

編集する

他の質問に対するコメントで、次の方法を見ました。sed

 sed 's,^\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\),\3/\2/\1,'

dateさて、私はコマンドに関連するタスクをどのように実行するのか疑問に思います。

答え1

すでに存在するループを試してみましょう(実際には見ていませんが、うまく機能しているようです)。

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done

それからそれを入れる他の質問に対する私の答え少し修正してください:

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done |
paste - <( cut -d ' ' -f 2- filedate.txt )

結果:

01/01/2007      10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007      10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007      10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007      10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

ループなしでより短く:

date -f <( cut -d ' ' -f 1 filedate.txt ) +"%d/%m/%Y" |
paste - <( cut -d ' ' -f 2- filedate.txt )

パイプがない場合:

paste <( date -f <( cut -d ' ' -f 1 filedate.txt ) +"%d/%m/%Y" ) \
      <( cut -d ' ' -f 2- filedate.txt )

これらすべての例には、明らかにプロセスの置き換えを理解する別のシェルがbash必要です。また、GNUが必要です。kshdate

バラより他の質問に対する私の答え仕組みの説明です。

答え2

目的の変換が既存の情報の順序を変更するだけであれば、これを試してみてはいかがでしょうか。

awk '{ $1=sprintf("%02i/%02i/%04i",
     substr($1, 7, 2), substr($1, 5, 2), substr($1, 1, 4)) }1' file

最初のフィールドから部分文字列を抽出し、それを最初のフィールドの新しい値に再組み立てし、通常どおり入力行全体を印刷します。 (中括弧の後の別の文字は、1無条件印刷用の標準Awk慣用語です。)

機械が完全に読むことができる日付を次のように変換すると、後悔する可能性があります。「人が読める」しかしすぐに。

答え3

GNU awk()がある場合は、gawkコマンド出力を使用して列を置き換えることができます。getline/変数/パイプ形式関数をgetline呼び出す方法は次のとおりです。date

gawk '{"date +%d/%m/%Y -d" $1 | getline $1} 1' file

ただし、列の日付形式のみを変更したい場合は、組み込み関数mktimeと関数を使用してstrftimeローカルで変更できます。

gawk '{
  d = sprintf("%d %02d %02d 0 0 0", substr($1,1,4), substr($1,5,2), substr($1,7,2));
  t = mktime(d);
  $1 = strftime("%d/%m/%Y", t);
  } 1' file

この場合、単純な文字列操作を使用して目的の変換を実行できます(この方法はすべてのスタイルに適用されますawk)。

$ mawk '{$1 = sprintf("%02d/%02d/%02d", substr($1,7,2), substr($1,5,2), substr($1,1,4))} 1' file
01/01/2007 10.2317 79.1638 6.0 26.7 20.9 0.8 14.0 98.6
02/01/2007 10.2317 79.1638 5.6 26.5 20.8 1.9 13.6 98.0
03/01/2007 10.2317 79.1638 7.5 27.7 20.8 0.1 15.8 96.4
04/01/2007 10.2317 79.1638 8.1 26.0 19.6 0.0 15.5 94.1

答え4

GNU sedコマンドのeval修飾子を使用すると、必要に応じて日付を変換できsます。date

sed -r 's|(\S+)(.*)|date -d \1 "+%d/%m/%y \2"|e'

置換された式は正しい形式の日付コマンドです。修飾子はeこのコマンドを各行に対して実行し、パターンバッファ(および出力)は各日付コマンドの出力に置き換えられます。

関連情報