前回に続き数値などを指定した形式(フォーマット)するprintfコマンドです。他のコマンドと組み合わせることでデータの生成・整形もできます。

今回もこれまでのようにサンプルで利用するファイル・ディレクトリはデスクトップのsampleディレクトリとしています。デスクトップにsampleディレクトリがない場合は作成しておいてください。(コマンド入力ならmkdir ~/Desktop/sampleとして作成することができます)
また、カレントディレクトリも上記の場所になります。cd ~/Desktop/sampleのようにコマンドを入力してカレントディレクトリを変更しておけばよいでしょう。

ファイル内の数値データをフォーマットする

 まず、ファイル内にある数値データをフォーマットして出力してみましょう。printfはパラメーターにファイルパスを指定できないため、xargsを使ってファイルの内容を渡すことにします。
 ここでは1.txtというテキストファイルを用意しました。1行に1つの整数値が書かれています。

・1.txtの内容

123
4
56
7890

これらの数値を8桁に揃えて表示するには以下のように指定します。以下のようにxargsを使うことで1.txtの内容が標準出力に流れ、その内容がprintfのパラメーターとして渡されます。

cat 1.txt | xargs printf '%08d\n'

結果をファイルとして保存する場合はリダイレクト(>)を使います。以下のように指定すると1a.txtというファイル名で結果が保存されます。

cat 1.txt | xargs printf '%08d\n' > 1a.txt

整数値を小数値(小数点以下2桁表示)として変換出力する場合は以下のように指定します。

cat 1.txt | xargs printf '%.2f\n'

上記の場合で十分な場合もありますが、桁数を揃え右揃えにして見た目をよくしたい場合もあるかもしれません。
そのような場合は全体の桁数と小数点以下の桁数の両方を指定します。以下のようにすると全体で8桁、小数点以下は第2位までの表示になります。

cat 1.txt | xargs printf '%8.2f\n'

複数列の数値データをフォーマットする

 次に1行に複数の数値がある場合です。数値はタブまたは半角空白で区切られているものとします。ここでは2.txtとして以下の内容のファイルを用意しました。

・2.txt

123 98 567 
4 7 11
56 781 657
7890 8760 31415

このデータを8桁で小数点以下2桁にする場合は以下のようにします。

cat 2.txt | xargs printf '%8.2f\n'

1データごと改行していますが、改行でなくタブ区切りにしたい場合は\nの代わりにタブコードを示す\tにします。

cat 2.txt | xargs printf '%8.2f\t'

CSV形式のように,区切りにする場合は以下のように指定します。

cat 2.txt | xargs printf '%.2f,'

今度は小数点を含むデータを整数値のみにしてみましょう。数値が書かれているデータファイル(テキストファイル)は以下のようになっています。

・3.txt

18.4
18.9
16.0
9.2
6.1
-0.3
-6.5
-1.2
0.01
3.8

この数値データを整数化するには以下のように指定します。%fでなく%dを指定するとエラーが出力されることがあります。

cat 3.txt | xargs printf '%.f\n'

3桁で綺麗に列を揃えたい場合は以下のように指定します。

cat 3.txt | xargs printf '% 3.f\n'

パイプを使いたくない場合はを使って実行結果をパラメーターとして指定することもできます。

printf '% 3.f\n' cat 3.txt

番号を振って出力する

 先ほどの3.txtのデータの前に番号を振ってみましょう。まず、シリアル番号を表示するにはseqを使います。以下のように入力すると1から10までの数値が表示されます。

seq 10

4桁で数値を揃えたい場合は以下のように指定します。

seq -f %04g 1 10

ただ、せっかくprintfを使ってきたのでseqとprintfを組み合わせてみましょう。以下のようにすると4桁での表示になります。

seq 10 | xargs printf '%04d\n'

この後の処理のために以下のようにリダイレクトを使ってnum.txtとしてファイルに書き出しておきます。

seq 10 | xargs printf '%04d\n' > num.txt

次は3.txtの前に4桁の番号をつけます。このような列を追加する場合、pasteコマンドを使えば簡単です。pasteのパラメーターに列を連結する順番でファイル名(ファイルパス)を指定します。以下のようにすると最初の列が4桁の番号、次が3.txtの内容の数値データになります。

paste num.txt 3.txt

ファイルに保存する場合はリダイレクトを使います。以下のようにするとdata.txtというファイル名で保存されます。

paste num.txt 3.txt > data.txt

データを,(カンマ)区切りにしたい場合は以下のようにします。

paste -d ',' num.txt 3.txt

日付を出力する

 番号ではなく日付と数値データという組み合わせにすることもできます。ただ日付の場合、数値と違ってコマンドのみで処理するのは無理なのでシェルスクリプトを作成します。
 日付の場合、単純に●年●月●日のような形式で●の値だけ変えればよいというわけにはいきません。このため日付を生成するためにUnix timeを利用します。Unix timeを表示するには以下のようにコマンドを入力します。

date +%s

上記の場合、コマンドを実行した時間なので実行するたびに結果が変わってしまいます。日付と時間部分を固定するには以下のようにします。以下の場合、2024年1月1日午前0時のUnix timeを表示します。

date -d "2024-01-01 00:00:00" +%s

上記のコマンドはLinuxでは動作しますがmacOSでは正常に動作しません。macOSでは-dの指定ができないためです。このためmacOSの場合は以下のように指定します。(以下のコマンドはLinuxでは動きません)

date -j -f "%Y-%m-%d %H:%M:%S" "2024-01-01 00:00:00" +%s

次にUnix timeを日付表示に戻す必要があります。macOSの場合は以下のようにします。

date -r 1704034800

Linuxの場合は以下のようにします。

date -d @1704034800

あとはシェルスクリプトで表示する日付範囲を繰り返します。説明していないものもありますが、そこら辺は動けばOKという連載スタンスなので大目に見てください。コマンドのオプションが違うのでLinux用とmacOS用で分けてあります。シェルスクリプトなのでchmod 755 d.shのように実行権限を付加した後に./d.shのようにコマンドを入力すると日付が表示されます。

・macOS用(d_mac.sh)

#!/bin/bash
start=1704034800  # 2024年1月1日
end=1704844800    # 2024年1月10日
current=$start
while [ $current -le $end ]; do
    m=`echo "$current"`
    date -r $m +"%Y年%m月%d日"
    current=$((current + 86400))
done

・Linux(d.sh)

#!/bin/bash
start=1704034800  # 2024年1月1日
end=1704844800    # 2024年1月10日
current=$start
while [ $current -le $end ]; do
    m=`echo "@$current"`
    date -d $m +"%Y年%m月%d日"
    current=$((current + 86400))
done

ここまでできれば番号を振る処理と同様にリダイレクトとpasteコマンドを使って日付と数値データをまとめることができます。

./d_mac.sh > d.txt
paste d.txt 3.txt
./d.sh > d.txt
paste d.txt 3.txt

ちなみに数値整形のみであればnumfmtコマンドというのもあります(macOSには入っていません)。 では、また次回。

著者 仲村次郎
いろいろな事に手を出してみたものの結局身につかず、とりあえず目的の事ができればいいんじゃないかみたいな感じで生きております。