AWKの質問です。

http://q.hatena.ne.jp/1227060292
の質問の続きになります。

最終的には回答の2番目(以下回答2)の方法を使いたいのですが、network(コメント参照)の中にの中に3.0.0.0のような「/」がないものがあり、回答2の方法では上手く動作しない箇所があります。従って回答2を使う前に

3.0.0.0  (スペース)next hop B5(スペース)その他データ
>(スペース)(スペース)next hop B6(スペース)その他データ
(スペース)(スペース)next hop B7(スペース)その他データ

のようなものがあったら上記データを全て削除する方法(AWKを使って)を教えてください。
質問の意図が分からなかったらコメント欄で質問してください。お願いします。

回答の条件
  • 1人3回まで
  • 登録:2009/01/08 12:27:16
  • 終了:2009/01/15 11:07:05

ベストアンサー

id:zzz_1980 No.2

zzz_1980回答回数492ベストアンサー獲得回数642009/01/08 18:30:05

ポイント95pt
/bin/sh
awk 'BEGIN{FMT="%s %s\n";skip=1} \
        match($0,"^[0-9]") !=0 && index($1,"/")!=0{skip=0;NEXTNET=$1;}  \
        match($0,"^[0-9]") !=0 && index($1,"/")==0{skip=1;}  \
        ($2==">" && skip==0 ){print NEXTNET,$3;} \
        ($1==">" && skip==0 ){print NEXTNET,$2;}' <$*
exit

適当な名前 hop.sh などに書いたうえ、hop.sh sample.data としてください。

行頭が数字で列1中に"/"がないものが現れたら、その先行頭が数字で列1中に"/"を含む行が現れるまで

スキップするようにしてみました。

その他の回答(1件)

id:zzz_1980 No.1

zzz_1980回答回数492ベストアンサー獲得回数642009/01/08 13:20:34

ポイント5pt

grep "/" で /を含む行だけ取り出してからawkにかければいいのでは。

id:zzz_1980 No.2

zzz_1980回答回数492ベストアンサー獲得回数642009/01/08 18:30:05ここでベストアンサー

ポイント95pt
/bin/sh
awk 'BEGIN{FMT="%s %s\n";skip=1} \
        match($0,"^[0-9]") !=0 && index($1,"/")!=0{skip=0;NEXTNET=$1;}  \
        match($0,"^[0-9]") !=0 && index($1,"/")==0{skip=1;}  \
        ($2==">" && skip==0 ){print NEXTNET,$3;} \
        ($1==">" && skip==0 ){print NEXTNET,$2;}' <$*
exit

適当な名前 hop.sh などに書いたうえ、hop.sh sample.data としてください。

行頭が数字で列1中に"/"がないものが現れたら、その先行頭が数字で列1中に"/"を含む行が現れるまで

スキップするようにしてみました。

  • id:labtest
    >zzz_1980さん

    いつも回答ありがとうございます。

    私が理解してないのか分からないのですが、

    network A2(スペース)next hop B5(スペース)その他データ
    >(スペース)(スペース)next hop B6(スペース)その他データ
    (スペース)(スペース)next hop B7(スペース)その他データ

    のデータがあるとして(network A2が「/」がある場合)

    grep "/" で /を含む行だけ取り出してしまうと

    欲しいデータの
    >(スペース)(スペース)next hop B6(スペース)その他データ
    も削除されてしまうと思うのですが。
  • id:zzz_1980
    ああ、そうですね。ちょっと勘違いしていました。顔洗って出直してきます。
  • id:labtest
    >zzz_1980さん

    新しく書いて頂いた方法を使ってみたのですが動かないようです。

    特に標準出力にも何も出力されず(ファイルに出力するようにしても何も書き込まれません。)終わったら

    sh-3.2>

    というshellが出てきてます。exitまで通っていないように見えます。

    zzz_1980さんの環境ではきちんと動いてますか?

    回答者1人につき3件まで回答を受け付けるように変更しました。
  • id:zzz_1980
    /bin/sh
    は#/bin/sh のまちがいです。全体がsh script でその中で awk を呼び出すようになっています。
    awk 単独でパイプラインの中にいれるのであれば、"\" を削除して ' から 'までを一行にした上で、
    % cat sample.data |awk_'{BEGIN{FMT="%s %s\n";skip=1}......'
    としてみてください。回答2は入力ファイルを指定するようになっています。
    space を全部 _ で置換してあります。
    % cat sample.data
    6.14.0.0/15_195.215.109.254_67768_0_3292_1239_701_668_i
    __216.218.252.164_0_6939_1299_701_668_i
    __74.40.7.36_0_0_5650_7018_701_668_i
    >_64.57.28.241_0_0_11537_668_i
    __200.160.127.238_0_27664_3549_701_668_i
    __202.147.61.12_1_0_10026_3356_701_668_i
    8.0.0.0/9_195.215.109.254_7888_0_3292_3356_i
    __202.76.224.242_0_24218_10026_3356_i
    __203.124.96.1_0_10075_703_701_3356_i
    >_74.40.7.35_0_0_5650_3356_i
    __207.246.129.13_0_11608_6453_3356_i
    8.0.0.10/9_>_195.215.109.255_7888_0_3292_3356_i
    __202.76.224.242_0_24218_10026_3356_i
    __203.124.96.1_0_10075_703_701_3356_i
    >_74.40.7.36_0_0_5650_3356_i
    __207.246.129.13_0_11608_6453_3356_i
    1.2.3.4_>_195.215.109.255_7888_0_3292_3356_i
    __202.76.224.242_0_24218_10026_3356_i
    __203.124.96.1_0_10075_703_701_3356_i
    >_74.40.7.36_0_0_5650_3356_i
    __207.246.129.13_0_11608_6453_3356_i
    % hop.sh sample.data
    6.14.0.0/15_64.57.28.241
    8.0.0.0/9_74.40.7.35
    8.0.0.10/9_195.215.109.255
    8.0.0.10/9_74.40.7.36
  • id:labtest
    >zzz_1980さん

    追加の質問ですみません。前回の回答2で一部は上手く動いたように見えたので書かなかったのですが、hop.sh sample.dataでは上手く動きませんでした。

    実はnetworkの前にスペースが2つあります。これを除くと上手く動きました。

    network A2(スペース)next hop B5(スペース)その他データ
    >(スペース)(スペース)next hop B6(スペース)その他データ
    (スペース)(スペース)next hop B7(スペース)その他データ

    上記の(スペース)はスペースの数が多いのですが。networkの前のスペースがあっても上手く動くように変更、もしくは「/」のあるところの最初の2つのスペースを削除する方法を教えて頂けないでしょうか?
  • id:zzz_1980
    | 実はnetworkの前にスペースが2つあります。これを除くと上手く動きました。
    そりゃそうでしょう。そういうサンプルデータで書いていますから。
    network の前にもスペースがある、となると
    __6.14.0.0/15_195.215.109.254_67768_0_3292_1239_701_668_i

    __202.76.224.242_0_24218_10026_3356_i
    の違いはなんだということになるのですが...
    "." の数でも数えますかねぇ...列の数は固定ですか?

  • id:zzz_1980
    入力データの「仕様」について取りまとめておいていただけますか。
    でないと、”実はこういう例外があって”の繰り返しでデスマーチ行きです。
    今回の回答でも、前回の回答にあった重複チェックは抜いちゃってますし。
  • id:labtest
    >zzz_1980さん

    大変お手間をおかけして申し訳ありません。
    何しろテキストファイルで300MB以上もあるため全ての例外を完璧に見ること(重複の存在等)が出来ません。それはご理解頂きたいと思います。ただそうは言ってもnetworkの前にスペースがあるという単純な情報をお伝えしなかったことは完璧に私のミスです。すみません。次のご回答で今回の質問は締め切らせて頂きます。

    全ての例外を今現時点で完璧に見ることが出来ないため、1度に通常の場合と例外の場合を含めて実現するのではなく、例外を削除(発見・編集等)するスクリプトと通常の場合を編集するスクリプトを分けて頂けると幸いです。例えばまず例外を見つけて削除するスクリプトを実施したのち、例外がなくなったものを編集するスクリプトを実施するという形です。

    そのため、前回から以下のことを出来る方法を教えて頂けないでしょうか?

    1.行の最初に二つのスペースがある場合、そのスペースを除く
    2.1の後にnetworkに「/」がないデータ群を除く(これは上記の回答2に近いものになると思うのですが)
    3.2の実施後にデータの整形を行う(これがhttp://q.hatena.ne.jp/1227060292の回答2になると思います)

    本当に申し訳ありませんがよろしくお願いします。わがままばかり言って申し訳ありません。
    AWKに固執しません。ただデータが300MBもあるのでperlで実施するより圧倒的に高速な方法をご教授願います。
  • id:zzz_1980
    1.行の最初に二つのスペースがある場合、そのスペースを除く
    は awk よりsed のほうが得意です。
    cat sample.data | sed 's/^__//'
    __ はスペースに置き換えてください。
    2.はたぶんそのまま。
    結局 sh + awk + sed なんですが、これは perl ひとつでできることです。自分にはできないですけどね。
  • id:labtest
    >zzz_1980さん

    どうもありがとうございました。
    大変助かりました。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません