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

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

ただいまの
回答率

91.02%

  • Linux

    3188questions

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

  • シェル

    230questions

    シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

シェルスクリプトでテキストの更新処理

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 156

say6

score 4

前提・実現したいこと

初心者です。

TXT01 と TXT02 という2つのファイルがあります。

TXT01は下記のDATAが入っています
ID     status
0001       A
0002       A
0003       A
0004       A
0005       B      

TXT02には下記のDATAです。
ID     status
0001      B
0002      B
0003      A

TXT02のレコードをTXT01に更新したいのですが、
状態の異なる0001と0002はA→Bに更新し、
0003は同じAでstatusが同じなのでエラーコードか
statusが同じですという戻り値を返したいということです。

bashかAWKでと思いますが、コードサンプルをご教授いただけると
大変助かります。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

仕様が曖昧な点がありますが、適当に想像して書いてみました。

更新後のTXT01をTXT01.newへ次のように出力したいと仮定します。(awkにせよ何にせよTXT01を同時に入力と出力の対象とすることはできませんので出力は一旦TXT01.newへ行うわけです)

ID status
0001 B
0002 B
0003 ERROR
0004 A <--TXT02に出現しないデータはそのまま
0005 B
(
  echo '-s-'
  cat TXT2
  echo '-e-'
  cat TXT1
) | awk '
/-s-/,/-e-/ { m[$1]=$2; next }
/^ID/ { print; next }
{ print $1" "((m[$1] != $2) ? $2 : "ERROR") }' > TXT1.new


いろいろ行儀が悪い点があります。(-s-,-e-を辞書mに登録してしまう点など・・・)


追記:

otnさんにコメントいただいたので平易と思われる方法を追記させていただきます。

awk '
!F { m[$1]=$2; next }
/^ID/ { print; next }
{ print $1" "((m[$1] != $2) ? $2 : "ERROR") }
' TXT2 F=1 TXT1 > TXT1.new

断然分かり易いですね!(まだイケテナイ部分は残っているだろうとは思いますが・・・)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/23 18:31

    大変ありがとうございます。もっとわかりやすく質問できるよう工夫します。
    参考にやってみます。

    キャンセル

  • 2017/11/23 20:20

    awkで複数ファイルに別々の処理をしたいとき、普通はこうします。
    awk '!F{ m[$1]=$2; next }~~' TXT2 F=1 TXT1

    キャンセル

  • 2017/11/23 20:25 編集

    そんな技が!
    コメントありがとうございます。
    ---
    If a filename on the command line has the form var=val it is
    treated as a variable assignment.
    この一文を長年気づかずに使ってきました・・・感謝です。

    キャンセル

  • 2017/11/23 20:33

    ありがとうございます。
    実は質問の仕方が悪く、TXT01の同一キー(ID)のstatusをファイル名そのままで
    TXT02のレコードと比較してA→Bに書き換えられないかという、質問でした。
    TXT02のレコードとTXT01のレコードを比較して、異なっていたらUPDATEするという
    ことですが、DBならなんということはないのですが、ファイルでやろうとすると良くわからず
    KSさんの回答から、無理かなと思いましたが、もし別解があるなら、アドバイスいただけるとありがたいです。
    sedでということかもと調べていましたが、辿りつけません。

    キャンセル

  • 2017/11/23 20:42 編集

    一旦TXT01.newに出力した後で、
    mv TXT01.new TXT01
    とすればよいだけでは?
    ---
    もし他のファイルへ一時的に出力したくないなら、通常のLinuxコマンドではなくCで専用のコードを書く必要がある気がします。テキスト処理が得意なUnix/Linuxですが、特定のファイルを直接書き換えるようなコマンドはパイプラインで繋げにくく、使い勝手が悪くなるため大抵のコマンドはstdinからstdoutへのフィルターとして設計されている気がします。

    キャンセル

  • 2017/11/23 21:01

    ありがとうございます。勉強になります。
    どうもDBの発想が抜けず、TXT01のレコードが数千とかの時のパフォーマンスを気にしました。
    頭の切り替えが必要だなと思いました。
    .newから元のTXT01に戻すとき差分だけとか(意味ないかも、とも思いますが)
    いくつか試してみます、ありがとうございました。

    キャンセル

  • 2017/11/23 21:06 編集

    > DBの発想が抜けず
    その気持ちはなんとなくわかる気がします。すごく巨大なテキストファイルならもう少し専用のプログラム・論理で立ち向かわなければならないかも知れませんが、例えば10万行ぐらいのものをバッチ処理すると考えると専用のプログラムを作るよりはフィルターの組み合わせ+最後にmvでも充分なパフォーマンスが出る気がします。色々試してみるとLinuxがすごく軽いOSであることを実感される気がします。

    キャンセル

  • 2017/11/24 07:41

    横から失礼
    「どうしても」元ファイルを直接更新したいのなら
    vi の操作を作って与えればいけると思いますが
    数千行とかいう話なら一時的にでもdatabaseを
    経由して処理しちゃう方がいいんじゃないのかなあ
    という気がしました

    キャンセル

  • 2017/11/24 15:33

    貴重なご意見ありがとうございます。
    更新となるとDBは楽だと思います。
    ゆえあって、脱DBに挑戦中でして、
    やってみたところ1万行程度なら、NEWファイル
    一瞬で終わりましたので、パフォーマンス気にすることは
    ないと思いました。
    ファイルのデータ量を必要最低限に抑えるため
    どのようにデータを分割保持するかが、肝だと思っていますが
    シェルコマンドに不慣れで、今後ともご指導お願いします。

    キャンセル

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

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

関連した質問

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

  • Linux

    3188questions

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

  • シェル

    230questions

    シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。