質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • Linux

    3768questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

  • bash

    645questions

    bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

  • AWK

    68questions

    AWKは、UNIX 上で開発されたプログラミング言語で、CSVファイルなどのテキストファイルの処理を目的にデザインされています。

Linuxで日本語が混ざったファイルを固定長で切り出したい

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 3,031

tpse

score 1

お世話になります。
初めて投稿するので、書き方が間違っていたり表現が不順分かも知れませんが、よろしくお願い致します。

前提・実現したいこと

Linux環境(UTF-8)で、日本語と半角英数字の混在したSQLスプールファイルから、固定長で文字列を抽出したい。

発生している問題・エラーメッセージ

日本語がUTF-8では3バイトで扱われるのか(?)、スプールファイルの行によってバイト数が違うため、cutやfoldでは固定長で切り出せず、awkのprintfで整形しても若干ずれてしまうようです。

該当のソースコード

(スプールファイル:sample.spool)※テキストエディタに貼って頂くと固定長と分かります

I173400 材料消費連携                                       高機能                                             B1A SR       材料消費連携                                       17/03/26 01:37:28 01734        08219
I124800 AB:取引先転送                                     AB:SYSTEM                                          B4A MREAL    AB:取引先転送 受信                                17/03/26 18:11:18 01248        03916
I125400 AB:工場転送                                       AB:SYSTEM                                          B4A MREAL    AB:工場転送 送信                                  17/03/26 18:11:18 01254        03928

試したこと

cut -b -120 sample.spool


I173400 材料消費連携                                       高機能                                             B
I124800 AB:取引先転送                                     AB:SYSTEM                                          B4A
I125400 AB:工場転送                                       AB:SYSTEM                                          B4A M

fold -b120 sample.spool|grep ^I


I173400 材料消費連携                                       高機能                                             B
I124800 AB:
I125400 AB:工場転送

LANG=C
cut -b -120 sample.spool


I173400 材料消費連携                                       高機能                                             B
I124800 AB:取引先転送                                     AB:SYSTEM                                          B4A
I125400 AB:工場転送                                       AB:SYSTEM                                          B4A M

LANG=C
fold -b120 sample.spool|grep ^I


I173400 材料消費連携                                       高機能                                             B
I124800 AB:取引先転送                                     AB:SYSTEM                                          B4A
I125400 AB:工場転送                                       AB:SYSTEM                                          B4A M

LANG=C
awk '{printf("%7s %-50s %-50s %3s\n",$1,$2,$3,$4)}' sample.spool


I173400 材料消費連携                                 高機能                                          B1A
I124800 AB:取引先転送                               AB:SYSTEM                                          B4A
I125400 AB:工場転送                                  AB:SYSTEM                                          B4A

お手数をお掛けしますが、ご教授いただければ幸いです。
よろしくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

日本語がUTF-8では3バイトで扱われるのか

いえ、2バイトのこともありますし3バイトのこともそれ以上のこともあります。

cutの-bオプションで指定する位置は「バイト位置」ですが上記のようにUTF-8では文字数あるいは文字の見かけの表示幅とバイト数は合致しません。-cオプションで「文字位置」を指定することもできますが、それもうまくいきません。なぜならこのファイルの形式はバイト数としても文字数としても「固定長ではないから」です。固定なのは「見た目の文字幅」だけであり、これはどちらかといえば可変長レコードと捉えたほうがよいでしょう。

ところで日本語を含むデータの場合、見た目の幅がバイト数に(ほぼ?)合致するという特殊な状況があります。それはShift-JISを用いた場合です。それを利用すると、切り出すときだけShift-JISとして扱うという手が使えます。

iconv -f UTF-8 -t SHIFT-JIS input | cut -b ... | iconv -f SHIFT-JIS -t UTF-8 >output

ただ注意が必要なのはUTF-8(というよりUNICODE)で表現できる全ての文字がSHIFT-JISで表せないことです。SHIFT-JISで扱える文字コードは(概ね)JIS第二水準までの漢字の範囲なのでその範囲なら上記の方法でうまくいくと思います。(もっと広い範囲を扱えるかも知れませんがJIS第二水準までなら確実といえるのではないかと思います。SHIFT-JISといっても若干バリエーションがあったりして混乱しますね・・・)

しかしそれを超える範囲の文字を扱う必要があるなら、文字数と文字幅を意識しながら切り出すようなスクリプトを書かなければならないと思います。(そういうことが簡単にできるコマンドがあるかも知れませんが残念ながら自分は知りません)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/28 00:22

    やはりUFT-8以外に変換すると良いのですね。。
    他の方法を知りたかったのですが、JIS第二水準までに十分収まる要件のようですので、iconvを採用します。
    どうもありがとうございました。

    キャンセル

0

SQL のスプールファイルの出力そのものをいじることができるのであれば、スプール側でカラムの区切りを設定してやって、切り出す側はその区切りを目印に行う(cut -f 区切り文字)という手が使えるかと思います。

タグにお使いのDBを追加するとよいアドバイスがもらえるかも知れません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/28 00:20

    ご回答ありがとうございます。
    可変長であれば如何様にもできるのですが、固定長を要望されていまして。。

    キャンセル

  • 2017/03/28 00:23

    いや、固定長になってないんですよね、そのスプールファイル。(固定長ならば、バイト単位で区切ればよいだけなので)
    スプールの出力で文字ではなくバイトで各カラムを制御してやらないと駄目ですよ?

    キャンセル

0

KSwordOfHasteさんのご回答の通り、iconvを使って一旦SHIFT-JISに変換してバイトでcut、表示用に改めてUFT-8に変換することで、綺麗に整形できました。

以前は 120バイトでカットしていましたが、見た目(SQLのform指定+ブランク)通り 113バイトでカットすることができました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    cronの設定についてどなたか教えていただけませんか

    何卒よろしくお願いいたします。 前提・実現したいこと Linuxのパソコンを使っています。 自作したshell scriptを毎回決まった時間に自動で動作させたいと思って

  • 受付中

    Linuxでログ出力のシェルスクリプトを作成

    前提・実現したいこと 新人インフラエンジニアです。(まだ現場未経験です) 先輩から課題をいただいたのですが、どうしても自力でできませんでした。 社内の検証環境がリリース作業で

  • 解決済

    linux lsコマンド 指定ディレクトリ除外

    ls $path -lR > aaa.txt 上記のようにlsコマンドを使って指定したディレクトリ内容を再帰的に表示(ディレクトリ内をすべて表示)したものをテキストファイルに

  • 解決済

    find 指定したディレクトリ除いて表示

    find /aaa/bbb/ccc |grep -v -f test.txt test.txt 内容↓ 45683 2016-01-01 13:30 /aaa/bbb/cc

  • 解決済

    linux ファイルパス表示(逆)

    findの結果を表示する際にフォーマットを指定しています。 フォーマット:"%M %2n %10s %TY-%Tm-%Td %TH:%TM %p\n" 表示例:-rwxrwxr

  • 解決済

    ls -l サイズ幅固定

    ls -lでの表示はファイルのサイズも表示してくれて、サイズ桁数が違っても終端を合わせて表示させていると思います。そのサイズ部分の幅を10ケタで固定させて表示させたいのですが、ls

  • 解決済

    xargs ls に対してgrepは可能?

    ls -lとコマンドをうつと、ファイルの情報が一行ずつ表示され、その一番上に”合計○○”と表示されると思います。それを非表示にしたいのです。 タイトル通りxargs lsに対

  • 解決済

    find YYYYMMDD_SEQからSEQのMAXを取得したい

    20161031_1 20161031_2 20161031_3 20161031_4 20161031_5 上記のようなディレクトリがあった時に"20161031"

同じタグがついた質問を見る

  • Linux

    3768questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

  • bash

    645questions

    bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

  • AWK

    68questions

    AWKは、UNIX 上で開発されたプログラミング言語で、CSVファイルなどのテキストファイルの処理を目的にデザインされています。