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

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

新規登録して質問してみよう
ただいま回答率
85.48%
AWK

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

Q&A

解決済

5回答

479閲覧

awkで1つのファイルを条件によって2つのファイルに分割したい

jjjr

総合スコア13

AWK

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

0グッド

0クリップ

投稿2018/11/10 05:06

編集2018/11/10 05:21

#プログラム初心者です。

前提・実現したいこと

awkを使用して、以下のファイルを2つに分割したいと思っています。

cat org.txt

@@@@@@@@@@@@
商品:りんご
産地:青森
補足:値引きあり
出荷状況:済み
@@@@@@@@@@@@
商品:みかん
産地:静岡
出荷状況:未
@@@@@@@@@@@@
商品:ぶどう
産地:山梨
出荷状況:済み

このファイルの“出荷状況”が“済み”と“未”の場合で以下のようにファイルを分割したいのです。

cat syukka.txt

@@@@@@@@@@@@
商品:りんご
産地:青森
補足:値引きあり
出荷状況:済み
@@@@@@@@@@@@
商品:ぶどう
産地:山梨
出荷状況:済み

cat misyukka.txt

@@@@@@@@@@@@
商品:みかん
産地:静岡
出荷状況:未

試したこと

awk初心者なのですが、配列を使うのかと試したのですが、太刀打ちできませんでした・・・
どのようにすればよいかご教授下さい。

以上、宜しくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

いわゆる「複行レコード」ですね。レコードセパレータの設定を変更すれば対応できます。

test.awk:

BEGIN{ FS="\n" RS="@@@@@@@@@@@@\n" } /出荷状況:済み/{print RS,$0}

sh

1$ awk -f test.awk org.txt > syukka.txt

投稿2018/11/10 08:17

KojiDoi

総合スコア13671

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jjjr

2018/11/10 08:48

ご回答ありがとうございます。 この発想はありませんでした。 色々と使えるテクニックだと思います。
guest

0

こんな漢字で、

bash

1$ cat org.txt|awk '/^@/{if(a)print a;a=$0};!/^@/{a=a"&"$0}END{print a}'|grep '出荷状況:済み'|tr '&' '\n' > syukka.txt 2$ cat org.txt|awk '/^@/{if(a)print a;a=$0};!/^@/{a=a"&"$0}END{print a}'|grep '出荷状況:未'|tr '&' '\n' > misyukka.txt 3 4$ cat syukka.txt 5@@@@@@@@@@@@ 6商品:りんご 7産地:青森 8補足:値引きあり 9出荷状況:済み 10@@@@@@@@@@@@ 11商品:ぶどう 12産地:山梨 13出荷状況:済み 14 15$ cat misyukka.txt 16@@@@@@@@@@@@ 17商品:みかん 18産地:静岡 19出荷状況:未

投稿2018/11/10 07:51

hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jjjr

2018/11/10 08:54

ご回答有難うございます。 後から特定文字を改行コードに変換して修正しているのですね。 勉強になります。
guest

0

Bash

1awk ' 2/^@@*/{save=$0;next} 3/^出荷状況:済み/{print save>"syukka.txt";print > "syukka.txt";next} 4/^出荷状況:未/{print save>"misyukka.txt";print > "misyukka.txt";next} 5{save=save "\n" $0} 6' org.txt

投稿2018/11/10 05:34

otn

総合スコア84557

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jjjr

2018/11/10 06:09

早々のご回答、有難うございます。 大変恐縮なのですが、一点サンプルに漏れがありました。 ”出荷状況”の下にも、場合によってコメントが入るケースがありました。 現状ご提示頂きましたコードの場合、出荷状況で区切っているのですが、 次の”@@@”が来る手前までで一つの纏まりとなるように認識させる方法はございますか? お手数をお掛け致しますが宜しくお願いします。
guest

0

KojiDoi さんの回答を元にして書いてみました。

a.awk

awk

1BEGIN { 2 FS="\n" 3 RS="@@@@@@@@@@@@" 4} 5/出荷状況:済み/ {print RS,$0 > "syukka.txt"} 6/出荷状況:未/ {print RS,$0 > "misyukka.txt"}

実行例
イメージ説明

追記:
org.txt の先頭に

#○○店 #出荷状況について

があった場合、 syukka.txt, misyukka.txt の先頭にもそれを出力するようにしてみました。
(上のコードでは、余分が改行が出力されていたので、 print -> printf に変更して余分な改行がでないよう修正もしています)

awk

1BEGIN { 2 FS="\n" 3 RS="@@@@@@@@@@@@" 4 out_0="misyukka.txt" 5 out_1="syukka.txt" 6} 7 8/#出荷状況について/ {printf $0 > out_0; printf $0 > out_1} 9/出荷状況:未/ {printf "%s%s", RS,$0 > out_0} 10/出荷状況:済み/ {printf "%s%s", RS,$0 > out_1}

実行例
イメージ説明

投稿2018/11/10 09:25

編集2018/11/10 10:59
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jjjr

2018/11/10 10:08

ご回答ありがとうございます。 私も先ほどご提案頂いたようなコードにしたところでした。 余談ですが、org.txtの先頭行に以下の行があった場合、 #○○店 #出荷状況について ”(空白)” この3行を作成した2つのファイルの先頭にも入れたいと思います。 (現在は別ファイルに分割しておき、catで足しています) 今回のawkのファイル中に併せて追加できるのでしょうか? やはり今回はレコードセバレータの設定を変更しているので、別コマンドの方が いいのでしょうか? 一旦解決済みにしていたのにすみません。
KojiDoi

2018/11/10 10:35

そのケースだと、RS変更後の「1行目」にそれらがまるごと入っているはずですね。NR==1のときにはそれらをそのままそれぞれのファイルに出力してあげるルールを追加し、既存のルールはNR>1 && /出荷状況:済み/{...}のように変更すればいいと思います。
jjjr

2018/11/10 10:52

ご返信ありがとうございます。 ただ今帰社した所なので、明日また挑戦してみます。
katoy

2018/11/10 10:59

回答に対処例を追記しました。
guest

0

デバッグしてないので、なんかあったらすんません

BEGIN{ s = "" f = 0 } /出荷状況:済み/ { f = 1 } /出荷状況:未/ { f = 2 } /@@@@@@@@@@@@/ && s != "" { if (f == 1) outf = "syukka.txt" if (f == 2) outf = "misyukka.txt" n = split(s, ss) for (i=1; i<=n; i++) { print ss[i] >> outf } s = "" f = 0 } { s = s,$0 } END { if (f == 1) outf = "syukka.txt" if (f == 2) outf = "misyukka.txt" n = split(s, ss) for (i=1; i<=n; i++) { print ss[i] >> outf } }

もし空白を含む行があったら改行がふえます。
--- 追記 ---

head -n 3 src.txt >syukka.txt cp syukka.txt misyukka.txt x=`wc -l src.txt` x=`expr $x - 3` tail -n $x src.txt | awk -f hoge.awk

投稿2018/11/10 06:51

編集2018/11/10 10:59
takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jjjr

2018/11/10 08:45

ご回答有難うございます。 すみませんが、下記の行はどのような動作を目的としているのでしょうか?  s = s,$0 以上、宜しくお願いします。
takasima20

2018/11/10 10:20

s = s $o だと直接連結になりますが、 s = s,$0 は間に空白を挟んだ連結になります。
jjjr

2018/11/10 10:53

ご返信ありがとうございます。 明日またテストしてみます。
takasima20

2018/11/10 10:59

失礼。tail のとこミスってました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問