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

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

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

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

Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

Linux

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

シェル

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

AWK

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

Q&A

解決済

5回答

1393閲覧

テキストファイルから複数指定した条件での抽出と加工

natsu25

総合スコア46

bash

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

Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

Linux

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

シェル

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

AWK

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

0グッド

1クリップ

投稿2020/07/09 10:13

text

1#start 2# 3# 4# 5# 6# 7# 8 9 10ID: 11223344556677 11NAME: XXXX-XXX 12MAIL: xxxxx@xxxx.ne.jp 13 14 15ID: 112233445566 16NAME: XXXXXX-XX 17MAIL: xxxxx@xxxx.ne.jp 18 19 20ID: 1122 21NAME: XXX-XXX 22MAIL: xxxxx@xxxx.ne.jp 23 24 25ID: 1234567 26NAME: XX-XXXXX 27MAIL: xxxxx@xxxx.ne.jp 28 29 30ID: 1122334455 31NAME: XXXXX-XXX 32MAIL: xxxxx@xxxx.ne.jp 33 34 35# search result 36search: 5 37result: 5 38 39# 40#end

上記のような形式のファイルから以下のような条件で抽出するにはどのような記述をすれば良いでしょうか?
先頭から7列目以降という条件は awk -F '=' 'NR > 8 {print $0}'" で出来そうかと思いますがその他の方法が分かっておりません。

① 先頭から7列目以降~末尾から8列目以前

② ①を除いたものから2列おきに3列ずつ取得

③ 取得した3列から改行を削除し1列にする
例:ID: 1122334455NAME: XXXXX-XXXMAIL: xxxxx@xxxx.ne.jp

④ID/NAME/MAILを抽出し別々のファイルに出力
※ID/NAME/MAILの文字数は定まっていないです。

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

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

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

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

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

natsu25

2020/07/09 11:00

はい、スクリプトの一部で表題の処理を組み込みたいのですが③も必要です。
hidezzz

2020/07/09 11:13

④の「別々のファイル」とは1件のIDとNAMEとMAILの単位で1ファイルずつ出力という意味?それとも全ID、全NAME、全IDの3種類でそれぞれファイルを作るという意味ですか?
natsu25

2020/07/09 12:09

>IDとNAMEとMAILの単位で1ファイルずつ出力という意味 こちらの意味です。分かりづらく申し訳ありません。
takasima20

2020/07/09 12:17

その場合のネーミングルールはどうなりますか?
guest

回答5

0

ファイル形式が確定しているのであれば
複数行レコードととらえて、改行をフィールドセパレータにすれば
すっきりしていいんじゃないかな。
各ファイルにレコードインデックスを添えると、のちのち便利かも。

awk

1#foo.awk 2 3BEGIN { 4 RS = "\n\n\n"; 5 FS = "\n"; 6} 7 8/^ID:/ { 9 sub(/ID: /, "", $1); 10 sub(/NAME: /, "", $2); 11 sub(/MAIL: /, "", $3); 12 printf("%04d %s\n", ++c, $1) >> "id.txt"; 13 printf("%04d %s\n", c, $2) >> "name.txt"; 14 printf("%04d %s\n", c, $3) >> "mail.txt"; 15} 16

awk

1awk -f foo.awk data.txt 2 3実行結果 4 5id.txt 60001 11223344556677 70002 112233445566 80003 1122 90004 1234567 100005 1122334455 11 12name.txt 130001 XXXX-XXX 140002 XXXXXX-XX 150003 XXX-XXX 160004 XX-XXXXX 170005 XXXXX-XXX 18 19mail.txt 200001 xxxxx@xxxx.ne.jp 210002 xxxxx@xxxx.ne.jp 220003 xxxxx@xxxx.ne.jp 230004 xxxxx@xxxx.ne.jp 240005 xxxxx@xxxx.ne.jp 25

補足解釈およびコメントをいただいて

awk

1#foo2.awk 2 3BEGIN { 4 RS = "\n\n\n"; 5 FS = "\n"; 6} 7 8/^ID:/ { 9 sub(/ID: /, "", $1); 10 sub(/NAME: /, "", $2); 11 sub(/MAIL: /, "", $3); 12 recfile = "rec" sprintf("%04d", ++c) ".txt" 13 printf("%s\n", $1 "/" $2 "/" $3) > recfile; 14}

awk

1awk -f foo2.awk data.txt 2 3実行結果 4rec0001.txt 511223344556677/XXXX-XXX/xxxxx@xxxx.ne.jp 6rec0002.txt 7112233445566/XXXXXX-XX/xxxxx@xxxx.ne.jp 8rec0003.txt 91122/XXX-XXX/xxxxx@xxxx.ne.jp 10rec0004.txt 111234567/XX-XXXXX/xxxxx@xxxx.ne.jp 12rec0005.txt 131122334455/XXXXX-XXX/xxxxx@xxxx.ne.jp

こんなんでいいのでしょうか。読解力なくてすみません。

投稿2020/07/09 22:20

編集2020/07/10 00:50
mfi.sub.jp

総合スコア6

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

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

Daregada

2020/07/09 23:57

質問者の説明が曖昧ですが、その後の補足によると、一件ずつ「ID/NAME/MAIL」をファイルにまとめて、データの件数分の個数のファイルを出力する、ということを言いたかったらしい。
mfi.sub.jp

2020/07/10 00:18 編集

コメントありがとうございます。 追記を読んで混乱。お題に「抽出」とあるように、どう見ても上記3ファイルの作成を意図しているように思うのだけれど、「1件のIDとNAMEとMAILの単位で1ファイルずつ出力」っていう変な質問で意味が分からなくなった。1レコードにつき1ファイル必要と言っているのかな?「抽出」どこいったんだろう。
guest

0

まあすべての条件を満たすとなるとperlが一番ラクじゃないでしょうかね
ちゃんとテストしてませんが、こんな感じで。

#!/usr/bin/env perl use strict; use warnings; my @data; while(<>){ chomp; push(@data, $_); } my $id=0; my $fho; foreach my $d (@data[7..$#data-8]){ if($d=~/^ID/){ $id++; open($fho, '>', "out$id.txt"); print {$fho} "$d\n"; }elsif($d=~/^NAME/ or $d=~/^MAIL/){ print {$fho} "$d\n"; } } close $fho;

投稿2020/07/09 13:29

KojiDoi

総合スコア13692

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

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

0

ベストアンサー

「列」と「行」を間違えてますね。

sedawkのようにフィルター的に処理するコマンドでは、「最後の8行を除外」は困難です。
案1:まず全体の行数を調べてから、処理を始める
案2:複数行をメモリ上に保存しながら処理する
のどちらか。

sh

1awk -v LINE=`wc -l < data.txt` 'NR>7 && NR<LINE-7 {~~~}' data.txt

sh

1awk '{data[NR]=$0}END{for(i=8;i<NR-7;i++){~data[i]の処理~}}' data.txt

ファイル全体がメモリに乗る量なら、案2が楽そうです。

sh

1awk '{data[NR]=$0}END{ 2 for(i=8;i<NR-7;i+=5){ print data[i+2] data[i+3] data[i+4]} 3}' data.txt

投稿2020/07/09 13:03

otn

総合スコア85901

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

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

0

別ファイルってことなので grep 使ってみました。

awk '/ID: /{id=$0} /NAME: /{name=$0} /MAIL: / {print id name $2}' hoge.txt grep 'ID' hoge.txt | sed 's/ID: //' >id.txt grep 'NAME' hoge.txt | sed 's/NAME: //' >name.txt grep 'MAIL' hoge.txt | sed 's/MAIL: //' >mail.txt

--- 追記 ---
仕様が違ったようなので

awk '/ID: /{id=$0} /NAME: /{name=$0} /MAIL: / {print id name $2}' hoge.txt grep -e 'ID' -e 'NAME' -e 'MAIL' hoge.txt | split -l 3

投稿2020/07/09 11:11

編集2020/07/09 12:30
takasima20

総合スコア7464

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

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

0

とりあえず③まで(,などのセパレーターは付けないでいいのかな?)

AWK

1awk '/^(ID|NAME):/ {printf $0 } /^MAIL:/ {print $0}'

投稿2020/07/09 11:04

Daregada

総合スコア11990

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問