こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

awkで特定の範囲の行を削除したい

awkなどの使い方がよくわからないので教えてください。
あるテキストファイル中の、"del_start" という文字が入った行から"del_end" という文字が入った行までの全ての行を削除したファイルを作るシェルを作成したいと思っています。
awk(やsed、grep、cat ?)などを使って実現するにはどうすればいいのでしょうか?

よろしくお願いします。

投稿日時 - 2006-09-28 20:48:24

QNo.2437956

すぐに回答ほしいです

質問者が選んだベストアンサー

del_startとdel_endは1回づつしか現れないのでしょうか。
だとしたら、これでいけます。

sed '/del_start/,/del_end/d' ファイル名 > 出力ファイル名

投稿日時 - 2006-09-28 23:02:07

補足

回答ありがとうございます。del_startとdel_endは1回づつです。えっ、こんな簡単にできちゃうんですか!!
明日確認して明後日以降に結果とお礼を書き込みます。

投稿日時 - 2006-09-29 01:24:23

お礼

うまくいきました。これだけでよかったんですね。ちなみにdel_startとdel_endが2回以上あってもちゃんと消せました。気の利いた簡単な解決策を教えていただけてよかったです。a-saitohさんありがとうございました。

投稿日時 - 2006-09-29 23:10:02

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

awk -f skip.awk data.txt
----------------------------------------------------------------
/^del_start$/,/^del_end$/{ next }
{ print }
----------------------------------------------------------------
一行に目印がdel_start だけが含まれているという条件です。
文中に含まれるというのであれば
/del_start/,/del_end/{ next }
にして下さい。

投稿日時 - 2006-09-29 05:00:58

お礼

これも簡単なやりかたですね。awkやsedは使いこなせるようになればシェルはずいぶんシンプルになるものなんですね。勉強になりました。
BLUEPIXYさんありがとうございました。

投稿日時 - 2006-09-29 23:14:40

ANo.2

こんなものでどうでしょう。

---Skip.awk----
BEGIN{
  ON = 1 # 初期設定
  OFF = 0

  Start="del_start"
  End ="del_end"

  Skip =OFF # 初期状態は、スキップしない
}

{
  if($0~Start) { # "del_start"を見つけると出力抑止(スキップする)
    Skip=ON
  }

  if(Skip==OFF) { # スキップしない行なので出力する
    print $0
  }

  if($0~End) { # "del_end"を見つけると出力を再開
    Skip=OFF
  }
}

gawk -f skip.awk data.dat data1.dat > result.dat

で、result.datにdata.dat、data1.datのdel_startからdel_endまでの行が消されたもの
をリダイレクトで作成します。

但し、del_startとdel_endの関係は
1)必ず一対一で対応している事。対応していない場合の動作検証はしていません。
2)ネストした場合の動作検証していない。
⇒この辺は、厳密な仕様を示していただけれは工夫してもいいですが、但し有料で(笑)

一部、細かいところを説明すると
 if($0~Start)とは、if($0~"del_start")と同じです。
 $0は行全体を指すので、行に"del_start"が正規表現的に含まれていれば真になります。
 ここで、Skip=ONとして出力を止めて、対象行以降を排除します。
 if($0~End)とはif($0~"del_end")と同じです。
 行に"del_end"が正規表現的に含まれていれば真になります。
 ここでSkip=OFFとして出力を再開します。

投稿日時 - 2006-09-28 21:50:27

ANo.1

こんなものでどうでしょう。

---Skip.awk----
BEGIN{
  ON = 1 # 初期設定
  OFF = 0

  Start="del_start"
  End ="del_end"

  Skip =OFF # 初期状態は、スキップしない
}

{
  if($0~Start) { # "del_start"を見つけると出力抑止(スキップする)
    Skip=ON
  }

  if(Skip==OFF) { # スキップしない行なので出力する
    print $0
  }

  if($0~End) { # "del_end"を見つけると出力を再開
    Skip=OFF
  }
}

gawk -f skip.awk data.dat data1.dat > result.dat

で、result.datにdata.dat、data1.datのdel_startからdel_endまでの行が消されたもの
をリダイレクトで作成します。

但し、del_startとdel_endの関係は
1)必ず一対一で対応している事。対応していない場合の動作検証はしていません。
2)ネストした場合の動作検証していない。
⇒この辺は、厳密な仕様を示していただけれは工夫してもいいですが、但し有料で(笑)

一部、細かいところを説明すると
 if($0~Start)とは、if($0~"del_start")と同じです。
 $0は行全体を指すので、行に"del_start"が正規表現的に含まれていれば真になります。
 ここで、Skip=ONとして出力を止めて、対象行以降を排除します。
 if($0~End)とはif($0~"del_end")と同じです。
 行に"del_start"が正規表現的に含まれていれば真になります。
 ここでSkip=OFFとして出力を再開します。

投稿日時 - 2006-09-28 21:48:17

補足

すばやい回答と丁寧な説明をありがとうございます。ON/OFFのスイッチを使うんですね。なるほど。明日試して見ます。明日は書き込みができないかもしれないので、明後日以降に結果とお礼を書き込みます。

投稿日時 - 2006-09-29 01:19:41

お礼

うまくいきました。del_startとdel_endが一対一対応していないとかのエラー処理までは考えなくていいのでこれで充分です。dennou2000さんありがとうございました。

投稿日時 - 2006-09-29 23:06:15

あなたにオススメの質問