出産前後の痔にはご注意!

UNIXで二つのファイルを使って別ファイルを出力する
処理をしたいのですが、awkで二つのファイルを扱う方法
が分かりませんでした。
やりたい処理は以下のような事です。

ファイルAの1行目"AAA B"と同じ行がファイルBにあったら、ファイルAの"AAA B"の次の行に、
ファイルBの次の行"YYY bbb"を挟み込みます。

もし、ファイルBに同じ行がなかったら、
ファイルAの次の行に"NG"を挟み込みます。

[ファイルA]
AAA B
ZZZ B
AAA C
ZZZ C
AAA D
ZZZ D

[ファイルB]
AAA B
YYY bbb
AAA C
YYY bbb

[出力ファイル]
AAA B
YYY bbb
ZZZ B
AAA C
YYY ccc
ZZZ C
AAA D
NG

どなたか良いスクリプトありましたら
教えていただけないでしょうか。
よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

perlで書くと、こんな感じでしょうか:



% cat a.pl
open( FA, $ARGV[0] ) or die;
open( FB, $ARGV[1] ) or die;
while ( $a = <FA> ){
print $a;
if ( eof( FB ) ){ undef $b; } else { $b = <FB>; }
print "NG\n" unless $a eq $b;
last unless defined( $b );
$a2 = <FA>;
$b2 = <FB>;
print $b2, $a2 if $a eq $b;
}

質問で出ている例だと、処理できますが、それ以外の場合は動作保証外ですな。
    • good
    • 0
この回答へのお礼

スクリプトありがとうございます。
試してみると、確かに出力結果が正しく出てくれました。
あとは、fileAの行が入れ替わっていても、差込が出来るように拡張してみたいと思います。
ただ、perlはawk以上に初心者なので、これを機会に勉強してみようと思います。
ありがとうございました。

お礼日時:2004/02/15 12:03

そういうときはdiffコマンドを使うと便利です。



参考URL:http://www.linux.or.jp/JM/html/gnumaniak/man1/di …
    • good
    • 0
この回答へのお礼

返答ありがとうございます。
diffコマンドは比較だけだと思っていたのですが、実際はいろんな処理が出来るんですね。
参考になりました。

お礼日時:2004/02/15 11:50

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qawkで複数ファイルをよんで$1$2と参照できるでしょうか?

awkで複数ファイルをよみこんでファイル1の$1ファイル2の$2と参照したりできないでしょうか?

Aベストアンサー

>この場合file1とfile2のデリミタを指定するには

デリミタが同じ","の場合
gawk -F, '{A=$1;getline < "file2";print A,$2}' file1

file1が","で、file2が" "の場合
gawk -F, '{A=$1;FS=" ";getline < "file2";print A,$2;FS=","}' file1
(行が読まれる時点でのFSの値で区切られます)

Q2つのファイル(.log)を比較し、条件が満たしているレコード(行)を抽出する方法

初心者です。

2つのファイル(.log)を比較し、条件が満たしているレコード(行)を抽出する方法を教えてください。



Aファイル

11.111.111
22.222.222
33.333.333
44.444.444


Bファイル

11.111.111.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
22.333.444.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
22.222.222.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
33.333.355.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
33.333.555.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
44.444.444.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200




Cファイル
11.111.111.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
22.222.222.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
44.444.444.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200


このように、AファイルとBファイルを比較し、結果をCファイルに抽出したいです。
エクセルでVlookupの関数を使う方法もありますが、Bファイルは容量が重いのでエクセルデータでは全部読み
取ることができません。
よって、UNIXコマンドでなんとか作業をしたいものです。
commを使う作業もありますが、手作業で不要な部分を削除していくのも大変なのでできれば自動化が希望です。

パソコンのOSはWin2000です。

どなたかご知恵をお借りください。
よろしくお願いします。

初心者です。

2つのファイル(.log)を比較し、条件が満たしているレコード(行)を抽出する方法を教えてください。



Aファイル

11.111.111
22.222.222
33.333.333
44.444.444


Bファイル

11.111.111.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
22.333.444.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
22.222.222.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
33.333.355.1111 [01/Jun/2007:00:00:00 +0000] "GET / test.html 200
33.333.5...続きを読む

Aベストアンサー

> しかし、ひとつだけ今日トラブルがありました…
> 私も考えていなかったので、質問には書かなかったのですが、
> ユーザIDと同じ名前が対象URLの中に紛れこむときもあるということです。

ああ、あえてその可能性には言及してなかったのですがそういうデータもありですか。

awkでやるなら話は簡単で、検索対象のフィールドを限定すればいいです。
$0 を対象にすると行全体からマッチするものを探していしまいますから、
期待するIDフィールドのところ(提示されたデータで判断すると$3)だけ
注目すればいいです。

ただこうすると、せっかくIDで探すときもIPアドレスで探すときも
共通のスクリプトが使えていたのに分離しなくてはならなくなるので、
何かの形で簡単なコマンドをAファイルの一行目に書けるとかしとくと
いいかもしれません。スクリプトに対するコマンドラインオプションでも
いいですけど。

NR==FNR {
chkitems[$0]=1
next
}

↑ここまでは共通で、

IPアドレスで検索するなら
{
for (idx in chkitems) {
if (index($1, idx) > 0)
print
}
}
こうで、
ユーザーIDで探すなら

{
for (idx in chkitems) {
if (index($3, idx) > 0)
print
}
}

> しかし、ひとつだけ今日トラブルがありました…
> 私も考えていなかったので、質問には書かなかったのですが、
> ユーザIDと同じ名前が対象URLの中に紛れこむときもあるということです。

ああ、あえてその可能性には言及してなかったのですがそういうデータもありですか。

awkでやるなら話は簡単で、検索対象のフィールドを限定すればいいです。
$0 を対象にすると行全体からマッチするものを探していしまいますから、
期待するIDフィールドのところ(提示されたデータで判断すると$3)だけ
注目すれば...続きを読む

Qawkで複数ファイルをそれぞれ集計し、一つのファイルに出力するには

awkプログラミングを始めたばかりの初心者です。複数ファイルのデータをそれぞれ集計し、一つのファイルに出力するにはどのようなスクリプトを作ればよいのでしょうか。


[file1]10,20,30

[file2]20,30,40

[file3]30,40,50

それぞれのファイルの中にある数字を合計して、別のファイル(file4)に一覧表示させる。
   ↓
[file4]60 90 120

Aベストアンサー

>notnotさんに提示していただいたスクリプトは、どのようにして実行させればよいのでしょうか。

シェルプロンプトでそのまま打ち込むか、あるいは、そのままシェルバッチスクリプト中に書けば良いです。

>awkを実行させるのに、「jgawk -f "プログラム名" "データ名" > "結果表ファイル名"」と、バッジファイルを作って実行させるやり方しか知りません。

' と ' に囲まれた中をpgm.awkに書いて、
awk -F, -f pgm.awk file1 file2 file3 > file4
としても良いです。

>各ファイルが複数行ある場合、どのようにすればよいのでしょうか。
・各ファイルの行数は同じ
・各ファイルの同一行数目の数字個数は同じ
とすると、awkプログラムを別ファイルに書く方式で示すと下記のようになります。

BEGIN{FS=","} #入力行のセパレータをカンマにする
{L=FNR;N[FNR]=NF #ファイル行数をLに、j行目の数字個数をN[j]に入れる
for(i=1;i<=NF;++i) SUM[FNR,i]+=$i} #j行目のi番目の各数字をSUM[j,i]に足しこんでいく
END{
for(j=1;j<=L;++j) {
for(i=1;i<N[j];++i) printf"%d ",SUM[j,i]
printf"%d\n",SUM[j,N[j]]
}
}

>notnotさんに提示していただいたスクリプトは、どのようにして実行させればよいのでしょうか。

シェルプロンプトでそのまま打ち込むか、あるいは、そのままシェルバッチスクリプト中に書けば良いです。

>awkを実行させるのに、「jgawk -f "プログラム名" "データ名" > "結果表ファイル名"」と、バッジファイルを作って実行させるやり方しか知りません。

' と ' に囲まれた中をpgm.awkに書いて、
awk -F, -f pgm.awk file1 file2 file3 > file4
としても良いです。

>各ファイルが複数行ある場合...続きを読む

Qawkを用いた複数ファイルのフィールドの結合方法

お世話になります。
gawkを使用しているのですが、

File1.dat File2.dat ・・・といった固定フィールドで行数は同一の2つ以上のファイルから特定のフィールドをそれぞれ抜き出し、1つのファイルへ出力する といったスクリプトの作成方法が分からず困っています。

ex--File1.datの$1と$3
1996 1 2
1996 1 3
1996 1 4

ex--File2.datの$4
90 500 11 33 0
94 445 18 71 0
85 512 29 68 0

ex--hoge.out
1996 2 33
1996 3 71
1996 4 68

いままで1つのファイルから切り出ししかせず勉強不足もあってお手上げ状態です。どなたかご存知の方いらっしゃいましたら宜しくお願いします。

Aベストアンサー

No.1です。うまくいきませんでしたか…。私の環境ではうまくいったのですが。

こういう方法はいかがでしょうか。
paste File1.dat File2.dat | gawk '{print $1,$3,$7}' > hoge.out

Qawk の int()に関数について

数値処理でawkを使い始めているのですが,
int関数を使って小数を切り捨てたいのですが,
以下のような現象が起こって困っています。

print int(9.53*100)
952 ?
print int(9.53*1000)
9530 OK
print int(65.52*1000)
65519 ?
print int(65.52*1000.0+0.1)
65520 ?

int関数はどういう動作をするのかどなたかご教示いただけますでしょうか。
お願いいたします。

Aベストアンサー

int()は実数値の整数部分だけを取り出す関数です。
合わないのは小数の誤差ですね。コンピューターは2のべき乗の和で表せる数値しか正確に表現できません。べき乗を ^ と書くと。

9.53=2^3+2^0+2^(-1)+2^(-6)+2^(-7)+2^(-8)+2^(-9)…

と無限に続き、正確には表せません。無限に続くのを途中で打ち切って10進数で書くと
9.52999999…
となります。

したがって、100倍して整数部分をとれば952になります。

解決方法としては、
案1) 小数点以下の値が出てこないように工夫して使う
案2) int(x+0.0000001) のようにする

QAWKで1項目以外を簡単に出力したい

awkのprint出力で$1$2$3$4$5$6と書くのではなく、$1から$6までを簡潔に指定できる方法はありませんか? (たとえば$1-$6のような)
すべて出力したい場合は$0でいいのですが、1項目だけ除外してあとはすべて出力したい時に項目が多い大変ですから。

Aベストアンサー

最後のフィールドだけ消せばいいのなら、組み込み変数NFをデクリメント
してやればいいです。$7=""だと中身が空のフィールドになるだけなので
余計なセパレータが出力されるように見えているのです。

ひょっとしたらNFをデクリメントしたあとで$0の再構築を
強制的にさせる必要があるかもしれません($0=$0 とか $1=$1で
やってくれるはず)。

QAWKにて時刻差分を取得したい

お世話になります。
現状、以下のログがあるのですが、

<snip>
日時, 通信開始時刻, 通信終了時刻・・・
2008/4/8, 14:00:00.3, 14:10:00.5, ・・・
<snip>

で、AWK(awk -F , )にて時刻差分を取得したいと考えたのですが、
$3-$2の出力結果が"0""-1"になり、表示されません。

うまく時刻差分を取得する方法はないでしょうか。
よろしくお願いいたします。

Aベストアンサー

基準時点からの経過秒数を返すのや日時の書式を整形するのはあるけど、A-Bのように直接日時を計算するような関数はなかったと思います。

他の言語でもそうですが、時間(文字列)を秒数に変換してから、計算するようにして下さい。

時間表記が「hh:mm:ss」の場合

num = split($2,time,":")
$2 = time[1] * 60 * 60 + time[2] * 60 + time[3]
num = split($3,time,":")
$3 = time[1] * 60 * 60 + time[2] * 60 + time[3]

$3 - $2

で経過秒が得られます。

参考URL:http://www.linux.or.jp/JM/html/GNU_gawk/man1/gawk.1.html

Q今、awkを使ったシェルスクリプトを作っています。

今、awkを使ったシェルスクリプトを作っています。

aaa bbb ccc ddd
ee ff gggg hhh

といったファイルから、
bbb,ccc
ff,gggg
を取り出したいと思っています。

そこで、以下のコマンドをwhileでまわして、$iを増加させることにより、
ファイルを一行ずつ読み取り、目的の列を取り出したく思っています。

A=`cat sample.txt|awk 'NR == $i {print NR, $2;}'`
B=`cat sample.txt|awk 'NR == $i {print NR, $3;}'`

ところが、awkコマンドの中の$iがシングルクォーテーションでくくられているので、
変数展開されなくて困っています。

何かよい方法があればご教授いただけますでしょうか?

Aベストアンサー

シングルが使えないならダブルでくくるとか
A=`cat sample.txt|awk "NR == $i {print NR, \\$2;}"`
-vオプションでawkの変数に代入するとか
A=`cat sample.txt|awk -v i=$i 'NR == i {print NR, $2;}'`


ですけど、そもそも、1行ずつ取り出すのに catで全部出力→awkで全部入力→1行だけ出力 って効率悪すぎませんか?

同じwhileを使うにしても
cat sample.txt | while read line
do
A=`echo ${line} |awk '{print $2;}'`
B=`echo ${line} |awk '{print $3;}'`
...
と1行ずつ処理するとか、bashだったら
cat sample.txt | while read line
do
declare -a a=($line)
A=${a[0]}
B=${a[1]}
と配列を使うとか
行番号が欲しかったら cat -n sample.txtにして $1に行番号を入れるか、i=`expr $i + 1` で行番号を数えるとか

あるいは
awk '{ NRと$2と$3を使った処理 }' sample.txt
とawkだけで済ましてしまう、とか

シングルが使えないならダブルでくくるとか
A=`cat sample.txt|awk "NR == $i {print NR, \\$2;}"`
-vオプションでawkの変数に代入するとか
A=`cat sample.txt|awk -v i=$i 'NR == i {print NR, $2;}'`


ですけど、そもそも、1行ずつ取り出すのに catで全部出力→awkで全部入力→1行だけ出力 って効率悪すぎませんか?

同じwhileを使うにしても
cat sample.txt | while read line
do
A=`echo ${line} |awk '{print $2;}'`
B=`echo ${line} |awk '{print $3;}'`
...
と1行ずつ処理するとか、bashだったら
cat samp...続きを読む

Qawkで本日日付の取得

awkで本日日付を取得する方法(組み込み関数)があれば教えてください。
できれば"20040121"といったフォーマットで取得したいです。

Aベストアンサー

その後の処理が面倒かもしれませんが
SYSTEM関数でUNIXのdateコマンドを呼び出してはどうでしょうか?

Qawkを用いて、特定の文字を含む以下の行を抜き出す

件名にあるように
awkを用いて、特定の文字を含む以下の行を抜き出したいのですが
どのようにしたらよいでしょうか?

具体的には
#cat text
aaaa
bbb ccc
<exe> aa
xxxxx vvvv
・・・

というようなファイルtextがあるとき
<exe> 以下の行すべてを抜き出したいです。
ご教授お願いします。

Aベストアンサー

awk '/<exe>/,0' text

でいけるかと。
<exe> が第一フィールドにあるときだけとかいう
条件があるなら

awk '$1~/<exe>/,0' text


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング