シェル・コマンドラインにおける処理に関して相談です。

SQL ServerのBULK INSERTの前処理なのですが、
以下のような行によってカラム数の差があるデータがあります。

カラム数が足りない場合に足りないカラムを空白で埋めたいのですが、
シェルやsedなどで対応できるコードを教えて下さい


2012-12-01 00:37:56 AAA JP 13
2012-12-01 01:37:56 AAA JP 15
2012-12-01 02:37:56 BBB
2012-12-01 03:37:56 AAA CN
2012-12-01 04:37:56 DDD JP 13

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2013/01/09 10:16:47
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:a-kuma3 No.1

回答回数4973ベストアンサー獲得回数2154

ポイント170pt

SQL Server ってありますが、unix 系とかでも良いんでしょうか。

質問で提示した例が、一番長い行が 29文字なので、一行が 29桁になるように末尾に空白を埋めます。
入力が input.txt で、出力を output.txt とします。

まず、sed の例。

sed -e 's/$/                             /' -e 's/^\(.............................\).*/\1/' input.txt > output.txt

29個の空白やピリオドを書くのが、うっとおしいですかね。
# vi 使えば、29i とかで数は合わせられますが。


awk だと、こんな感じ。

#! /usr/bin/sh
awk '
BEGIN { PAD = "                             " }   # 29個の空白
{
    print substr($0 PAD, 0, 29)
}
' input.txt > output.txt

awk スクリプトの内容をファイルに書いておいて、-f オプションで指定しても同じです。




タブ区切りだってことで、全面的に改定。

#! /usr/bin/sh
awk '
BEGIN {
    FS = "\t"
    OFS = "\t"
}
NF == 1 { print $0 "\t \t \t " }
NF == 2 { print $0 "\t \t " }
NF == 3 { print $0 "\t " }
NF == 4 { print }
' input.txt > output.txt

ちょっとカッコ悪い?

カラム数を、定数で持ってみたパターン。

#! /usr/bin/sh
awk '
BEGIN {
    FS = "\t"
    OFS = "\t"
    REC_N = 4       # カラム数
}
{
    printf "%s", $0
    n = REC_N - NF
    for (i = 0 ; i < n ; ++i) {
        printf "\t "
    }
    printf "\n"
}
' input.txt > output.txt

4カラムにしているのは、日付と時刻の間はタブではなくて、スペースだろう、という想像からです。

他3件のコメントを見る
id:masakiplus
  • cはコンパチブルで古いawkと言う意味です。

cygwinだとawkではなくて、拡張されているgawkなので、一応つけてみました

2013/01/09 16:20:03
id:a-kuma3

http://linux.die.net/man/1/gawk
--compat と同義なわけですね。

でも、手持ちの gawk じゃ、通らないなあ。
亜種があっても不思議ではないですが。

2013/01/09 21:15:16

その他の回答1件)

id:a-kuma3 No.1

回答回数4973ベストアンサー獲得回数2154ここでベストアンサー

ポイント170pt

SQL Server ってありますが、unix 系とかでも良いんでしょうか。

質問で提示した例が、一番長い行が 29文字なので、一行が 29桁になるように末尾に空白を埋めます。
入力が input.txt で、出力を output.txt とします。

まず、sed の例。

sed -e 's/$/                             /' -e 's/^\(.............................\).*/\1/' input.txt > output.txt

29個の空白やピリオドを書くのが、うっとおしいですかね。
# vi 使えば、29i とかで数は合わせられますが。


awk だと、こんな感じ。

#! /usr/bin/sh
awk '
BEGIN { PAD = "                             " }   # 29個の空白
{
    print substr($0 PAD, 0, 29)
}
' input.txt > output.txt

awk スクリプトの内容をファイルに書いておいて、-f オプションで指定しても同じです。




タブ区切りだってことで、全面的に改定。

#! /usr/bin/sh
awk '
BEGIN {
    FS = "\t"
    OFS = "\t"
}
NF == 1 { print $0 "\t \t \t " }
NF == 2 { print $0 "\t \t " }
NF == 3 { print $0 "\t " }
NF == 4 { print }
' input.txt > output.txt

ちょっとカッコ悪い?

カラム数を、定数で持ってみたパターン。

#! /usr/bin/sh
awk '
BEGIN {
    FS = "\t"
    OFS = "\t"
    REC_N = 4       # カラム数
}
{
    printf "%s", $0
    n = REC_N - NF
    for (i = 0 ; i < n ; ++i) {
        printf "\t "
    }
    printf "\n"
}
' input.txt > output.txt

4カラムにしているのは、日付と時刻の間はタブではなくて、スペースだろう、という想像からです。

他3件のコメントを見る
id:masakiplus
  • cはコンパチブルで古いawkと言う意味です。

cygwinだとawkではなくて、拡張されているgawkなので、一応つけてみました

2013/01/09 16:20:03
id:a-kuma3

http://linux.die.net/man/1/gawk
--compat と同義なわけですね。

でも、手持ちの gawk じゃ、通らないなあ。
亜種があっても不思議ではないですが。

2013/01/09 21:15:16
id:masakiplus

サーバーはSQLですが、cygwinの上、各種ツールはインストール済みです(sed/awk/pyhton/Perlなど)。

また、ファイルはTAB区切りのファイルで、

カラムが足りない行はTABで埋めていく必要があります。

id:oil999 No.2

回答回数1728ベストアンサー獲得回数320

ポイント130pt

まず確認ですが、

2012-12-01 00:37:56 AAA JP 13 →5つのカラムがある
2012-12-01 02:37:56 BBB →3つのカラムしかない

という状況で、すべての行を5つのカラムに統一したいというご質問ですね。

変換前のデータを "hoge.txt" というファイル名で保存してください。
Windowsであれば、gawk を使って以下のようにします。
http://www.vector.co.jp/soft/win95/util/se376460.html

カラム区切りをカンマにしています。

gawk "{ for (i=1; i<5; i++) { printf(\"%s,\",$i); } print $5; }" hoge.txt
id:oil999

タブ区切りであれば、以下のようにしてください。
足りないカラムはタブで埋めます。

gawk "{ for (i=1; i<5; i++) { printf(\"%s\t\",$i); } print $5; }" hoge.txt > out.txt
2013/01/09 08:13:58
id:masakiplus

ありがとうございます。
こちらは試していないですがcygwinだと\tなどを¥tなどに変える必要があるかもしれません。
感謝です!

2013/01/09 10:15:59

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません