• ベストアンサー

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

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

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

  • ベストアンサー
  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.3

del_startとdel_endは1回づつしか現れないのでしょうか。 だとしたら、これでいけます。 sed '/del_start/,/del_end/d' ファイル名 > 出力ファイル名

abekkan
質問者

お礼

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

abekkan
質問者

補足

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

その他の回答 (3)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.4

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

abekkan
質問者

お礼

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

回答No.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として出力を再開します。

回答No.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として出力を再開します。

abekkan
質問者

お礼

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

abekkan
質問者

補足

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

関連するQ&A

  • ある単語を含む行と、1つ前の行とを削除するシェル

    UNIX初心者です。 シェル(Korn)で、あるファイル中に、単語 "iwa"を含んだら、その行と、1つ前の行とを削除したいシェルを作りたいのです。  つまり、grep, sed, awk などで、"iwa"を含む行がみつかったら、その行(iwaを含む行)と、なおかつ、1行前の合わせて、2行を削除するシェルを作りたいのですが、行番号(NR?)などを使うのでしょうか? よろしく、お願いします。

  • awkで可変文字列をマッチング

    シェルなどでawkを使う際に、シェルの引数として渡された文字列をawkに渡し、それを条件にマッチングをかけたいのですが、どうしたら良いのでしょうか?(まあ、素直にgrepを使えばいいのですが・・・) 例えば、 cat foo.txt | awk '{if ($2 == ptn) print}' ptn=$<シェルの引数> とかやれば、2番目のフィールドに完全に一致する行が抽出できるのですが、 cat foo.txt | awk '/ptn/ {print}' ptn=$<シェルの引数> とかやっても、"ptn"という文字列をマッチングしてしまうので、うまくいきません。どの位置に出現するかわからないけど、シェルの引数で指定された文字列が含まれている行だけを出力したい場合、どうしたらよいのでしょう・・・。

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

    件名にあるように awkを用いて、特定の文字を含む以下の行を抜き出したいのですが どのようにしたらよいでしょうか? 具体的には #cat text aaaa bbb ccc <exe> aa xxxxx vvvv ・・・ というようなファイルtextがあるとき <exe> 以下の行すべてを抜き出したいです。 ご教授お願いします。

  • perlで特定行から特定行までを抜き出しor置換

    perlで以下のようなことをしたいと考えています。 以下のことを、コマンドラインから「perl ~」という形で 実行したいのですが、どのよにすればよいでしょうか。 1.特定行から特定行までを抜き出し 2.特定行から特定行の範囲で文字列置換 例えば、次のようなテキストファイルがあったとします。 example.txt ================================== #START aaaa hogehoge test okok perl script #END ================================== 上記ファイルを読み込んで、 1.「#START」から「#END」の間に挟まれた行だけ抜き出し 2.「#START」から「#END」の間で、「test」を置換 のです。 sedで言うところの sed -e '/#START/,/#END/ s/YYYYMM/201603/g' test.txt をやりたいのです。

    • ベストアンサー
    • Perl
  • awkでn行目までを1行に入れたい

    awkを使ってこの問題を解決できるかどうか教えてください。 次のようなファイルがあるとします。 各行には第1フィールドしか値がありません。 $cat aaa 11111 22222 33333 44444 55555 66666 このファイルを次のように並べ替えたいです。 11111 22222 33333 44444 55555 66666 3行目までの値を1行目に入れ、 次の4行目から6行目までの値を2行目に入れていきたいです。 使用する環境は、solaris,Linuxの混在環境です。 awkで実現できるのではないかと考えていますが、もしできなければその他の方法を教えて頂ければありがたいです。 宜しくお願いします。

  • シェルで文字列を含んだ行だけを削除したい!

    文字列を含んだ行だけを削除したいと思って、 sed -e "/XXXXXXXX/d" destfile > destfile または grep -v XXXXXXXX destfile > destfile とやったら、全部消えてしまいました!(^^;) どうしてですか? そして、どうしたら正しい処理になりますか? すみません。シェル初心者です。 易しく、わかりやすく、教えて下さい!

  • sed,awkでのデータ抽出方法

    教えてください。 awk,sed,シェルを使い、カンマ区切りのファイルの1カラム目と2カラム目をキーに、 あるファイルに含まれる行を削除するにはどうすればよいのでしょうか? 例) --aaa.csv-- 111,222,333,444 555,666,777,888 999,000,111,222 --file1.txt-- 111222 555666 の場合、aaa.csvより下記行のみほしい。 999,000,111,222 ご存知でしたら、ご教授ください。 よろしくお願いします。

  • awkで列指定をして削除

    awkかsedを利用して以下のファイルを処理したいです。 1 2 3 4 5 2 1 3 4 5 1 2 3 4 5 3 1 3 4 5 一列目の値が1の行のみ削除したいです。 2 1 3 4 5 3 1 3 4 5 こんな感じです。 実際に処理するファイルは膨大な行数ががあるためprintでは難しいです。 よろしくお願いします。

  • 特定の文字列を含む行だけ削除する方法?

    いつもお世話になっています。 Unixであるテキストファイルから、 特定の文字列を含む行(レコード)だけを 削除する方法を教えてください。 現在、grepを使って、いろいろ試しているのですが、 正規表現で、 ”***”を含まない行(レコード)だけを 切り出すとう正規表現の説明が見あたりません。 "^**"は、**以外の文字を検索できるようですが、 文字列に対しては、使えません。 grep以外の方法でも良いのですが、 なるべくシンプルにできる方法がありましたら 教えてください。 宜敷お願いします。

  • awkについて

    awkについて 今とあるファイルの/var/tmp/test 中の検索についてawkを使用しています。 123 abc 123-m 333 aaa-xx 1qwoko などタブキーで区切られています。 cat /var/tmp/test grep 123 | awk '$=="123"{print $2}' とやった場合存在するので 結果がでるのですが、その結果がない場合"NG"など文字列を出したいのですがどうすればいいでしょうか?