grep,sedコマンドについて

このQ&Aのポイント
  • grepコマンドとsedコマンドを使用してファイルの数字と時間の部分を削除する方法について質問します。
  • grepコマンドで削除部分を抽出し、sedコマンドで行を削除する方法を検討していますが、具体的な方法がわかりません。
  • 質問した内容について、grepコマンドとsedコマンドを組み合わせて適切に行削除を行える方法を教えてください。
回答を見る
  • ベストアンサー

grep,sedコマンドについて

昨日に引き続き、またまた質問です。 昨日回答してくださった方、ありがとうございました。 その後自分でも色々勉強しまして、ファイルの中身を処理するにはgrepコマンドとsedコマンドが 有効である事が分かりました。 今回やりたいことは以下のファイルの数字と時間の部分(//のついている2行)の削除です //1 //00:00:03,600 --> 00:00:07,195 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx //2 //00:00:07,360 --> 00:00:09,635 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx     ・     ・ (実際のファイルには"//"はついていません) 理想の出力 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx (xxxxxの部分には英語の台詞が入ります) で、以下が自分が考えた方法です 1.sedコマンドのみで削除 $ sed "/[0-9]*\n[0-9][0-9].*/d" ファイル名 結果 ファイルの内容がすべて表示されるだけ (a) 2.grepコマンドで抽出しパイプ処理 まずgrepで削除部分を抽出 $ grep -P "^[0-9]*\n[0-9][0-9].*" ファイル名 結果 1    00:00:03,600 --> 00:00:07,195    2    00:00:07,360 --> 00:00:09,635         ・         ・    10    11         ・         ・ となり、1~9までの数字と時間はちゃんと表示され 10以降は数字しか出ません。 (b) また -P の部分を -E にすると、何も表示されません (c) (perlの正規表現と拡張正規表現の違いはここでは無いように思えますが・・・) 2は最初でつまづいたのでどのコマンドに渡して行を削除するかはまだ分かりません (d) 削除の際、2行まとめて行うのは、一行ずつ行うと、台詞の部分に数字のみが入っていた場合 削除されるのを防ぐためです 以上長くなりましたが(a)~(d)の質問、疑問に回答していただけると嬉しいです。 よろしくお願いします。

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

  • ベストアンサー
  • ky072
  • ベストアンサー率60% (85/140)
回答No.2

元のファイルを SRC.txt とします。 (a) sed はデフォルトでは複数行を読み込みません。 Nコマンド等で次の行をパターンスペースに読む必要があります。  % sed '/^[0-9][0-9]*$/{N;/[0-9][0-9]*\n[0-9][0-9].*/d}' SRC.txt (b) [0-9]* を [0-9]+ にすれば解決します。 * は 0 文字にもマッチするため、 「10」の上の空行にマッチしていると思われます。 (c) 通常、複数行にマッチするような正規表現は grep で使いません。 -P オプションを付けた場合のみ、改行にマッチさせられるようです。 (d) 懸念されている「数字のみの台詞行」を無視するなら、 grep で簡単にできます。 % egrep -v '^([0-9]+|[0-9:, ]+-->[0-9:, ]+)$' SRC.txt 厳密にやりたいなら awk や perl がおすすめです。 % awk '{if(/^[0-9:, ]+-->[0-9:, ]+$/&&b~/^[0-9]+$/){getline;b=$0;getline;}print b;b=$0;}END{print b}' SRC.txt

airrace
質問者

お礼

回答ありがとうございます >% sed '/^[0-9][0-9]*$/{N;/[0-9][0-9]*\n[0-9][0-9].*/d}' SRC.txt これでは出来ませんでしたが、 $ sed 'N;/[0-9]\+\n[0-9][0-9].\+/d' で、ある程度は削除できましたが、いくつか残ったままのところもあります >[0-9]* を [0-9]+ にすれば解決します。 おっしゃる通りで、見事解決しました(^^) >厳密にやりたいなら awk や perl がおすすめです。 どちらもまだ知りませんが、おいおい習得しようかと思います。 sedコマンドで成功させるにはどうしたらよいのでしょうか? grep -P "^[0-9]+\n[0-9][0-9].+"では削除対象の行が正しく表示されます

その他の回答 (4)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

単に「できない」というのではなく, 何がどう「できない」のかを書いてもらえませんかね. N で追加する文字列が「削除すべき 1行目」だったりすると問題になりそうですが, そういうことですか?

airrace
質問者

お礼

はじめに 色々触っていたら以下のコマンドで遂に成功しました。 sed '/[0-9]\+/N;/[0-9]\+\n[0-9][0-9].\+/d' >単に「できない」というのではなく, 何がどう「できない」のかを書いてもらえませんかね. 自分でもそれが分かりませんでした。と言うのも、 sed 'N;/[0-9]\+\n[0-9][0-9].\+/d' を行ったとき、(自分が見る限りでは)不規則に、成功する行(数字のみの行と時間の削除) と成功しない行があったので。

  • pakuti
  • ベストアンサー率50% (317/631)
回答No.4

難しく考えないで grep -v "^[0-9]\+" |grep -v "^[0-9][0-9]:" で、事足りるのでは?

airrace
質問者

お礼

回答ありがとうございます はい、おっしゃる通りで、そうすれば必要な部分のみを表示させることが出来ますね ただ、台詞が数字の時は表示されませんが・・・ あっ、この投稿をみて閃いたのですが 必要な部分(台詞で数字のみの部文も)をgrepで取ってリダイレクトすればいいのか!! grep -v -P "^[0-9]+\n[0-9][0-9].+" 入力ファイル >> 出力ファイル で、出来ました(^^) でも、なんでsedでは出来ないんですかね?もう少しだと思うのですが

回答No.3

問題点をあげると、 まず正規表現を渡すとき、シェルの変数をつかわないかぎりは、""ではなく''で囲った方がいいです。 ''は囲まれた文字列をそのままgrep やsedに渡してくれるので、ワイルドカードとして当てはまるからと、 シェルに改変されずにすみます。 つぎに、sedやgrepは基本は行単位で一行ずつ読み込みをして改変するということです。 /[0-9]*\n[0-9][0-9].*/などは2行におよんでいるために理解してもらえません。 (もしかしたら行単位でなく読み込んだりできるのかもしれませんが、自分は詳しくなくて、、すいません。) なのでこの場合、数字だけの行を消すのと、数字と:が混じった行を消すのとで二つ分正規表現を書きます。 あるいは、アルファベットが含まれない行だけを出すという表現なら一つの表現でも大丈夫です。 (もしかしたら、最初の数字だけの行を消したあと必然的にその下の行を消すなんて表現もあるかもしれませんが、すいません、自分の勉強不足ゆえに分かりません。。。) また、後半の.*ですが、これは指定してもしなくても代わりありません。 sedのdは、マッチした行そのものを消すわけですので、.*以前の[0-9][0-9]でマッチすればその行を必然てきに行全体を消してしまいます。 *などを利用するのはdで○○しかない行をとか、sの変換置換で、ここまでを置換するという範囲指定のときに使われます。 sedを使うならば、 $ sed '/^[0-9]*$/d;/^[0-9][0-9]:/d' hoge.txt でしょうか。 一応説明すると、 '/^[0-9]*$/d' と '/^[0-9][0-9]:/d'というのを;でつないで 連続して行うようになってます。 最初のは、行が数字のみを削除するを表し、 次のは、先頭に数字二回のあと:がくる行を削除をしめしてます。 grep で行うならば先言ったアルファベットが含まれる行を表示として、 $ grep '[a-zA-Z]' hoge.txtとか、 $ grep '[[:alpha:]]' hoge.txtとか、(これはアルファベットすべてを表すクラスという表現) ですね。 (grep にも正規表現に当てはまらない行のみを表示するというあまのじゃくな-vオプションというのがあり、 これをつかえば、sedのように該当行のみ表示させないとできますが、 今回は該当行のみ表示させないと表現するのに二つ正規表現が必要で、 grepに条件を復数していする方法は、自分、くわしくないのですいませんわかりませんでしたので載せません。) grep や sed を使うときは、 それらが基本は行を一行ずつ処理していくということを 頭において考えるとうまくいきます。 そして、正規表現ですが、 馬鹿みたいにたくさん種類がありますので、 基本使いそうなものをいくつか覚えておくと便利です。 こういうコマンドって便利なのでぜひ頑張ってください。

airrace
質問者

お礼

回答ありがとうございます >$ sed '/^[0-9]*$/d;/^[0-9][0-9]:/d' hoge.txt 実行しますと、確かに「数字のみの行」と「時間の行」は削除できますが 「台詞が数字のみの行」も削除されてしまいます。 あと、なぜか空白行 n 時間 台詞      ←(ここです) n+1 時間 ・ ・ も削除されてしまいます。 自分は sed 'N;/[0-9]\+\n[0-9][0-9].\+/d' を適切にいじれば解決すると思うのですが・・・

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

sed ならできそうな気もするけど, perl があるならそっちの方がはるかに楽.

airrace
質問者

お礼

回答ありがとうございます perlを使ったことがないので・・(汗)

関連するQ&A

  • unix sedコマンドについて

    file --------------------------------------- abcdefghijklmnopqrstu abcdefghijklmnopqrstu person=aaa wake walk work abcdefghijklmnopqrstu abcdefghijklmnopqrstu --------------------------------- といったファイルにて このファイルからperson~空白行を「sedコマンド」で削除したいのですがどのようにしたらよいでしょうか。 sedコマンドを使用すると、どうやら、数行あるテキストを一行にまとめ、空白行を見つけたらその行を削除するといった動きになるようです。(一行でそれを行うのでしょうか。。) どなたか、わかる方いたら教えていただけないでしょうか。 よろしくお願いします。

  • sedコマンドによる最終行の削除について

    sedコマンドを使用してファイルの最終行を削除する方法を調べていたのですが 最終行の削除は問題なくできたのですが最終行から特定行までを消すため以下のコマンドを発行したのですがうまくいきませんでした。複数サイトを見てみたんですが構文自体は同じでしたのでおそらく問題ないとは思うですが何か気づく方がいたらお教えください。 以下実行コマンド sed -e '$-3,$d' sed_test.txt

  • sedコマンドで指定の行まで削除

    sedコマンドで1行目から、例えば「FLAG」と書かれた行までを削除したい場合どう書けばよろしいでしょうか。 sedコマンド以外に有用なコマンドがあれば、そちらも教えていただきたいです。 よろしくお願いします。

  • linuxのgrepコマンドに関して

    linuxのgrepコマンドに関して ファイルの中から、1や2という文字が単独で存在する行を検索したくて grep 1 file名 とするのですが、そうすると11や23など文字が単独ではなく、含まれている行が出力されます。 含まれる、ではなく文字そのものを検索するにはどうしたらよいでしょうか?

  • grepの出力結果の保存

    LinuXのgrepコマンドに関する質問です。 既存のファイルからgrepコマンドで特定の文字列が含まれた行だけを抽出し、その行数を数えるという課題です。 行数を数えるのでwcコマンドを使おうと思ったのですが、wcコマンドは「wc (ファイル名)」という使い方をしますよね。 ということは、grepコマンドで抽出した結果をファイルに保存しなくてはならないのですが、やり方がわかりません。

  • sedコマンドについて

    sedコマンドについてご存知の方いたらお願いします。 cn: main=bread, fruit=apple, drink=coffee, dessert=cake といった文字列があった場合、 fruit=apple だけを「sed」コマンドを使用して 表示あるいはファイルへ出力する方法を教えていただけないでしょうか。 よろしくお願いします。

  • 改行を含んだgrep

    お世話になっております。質問です。 エディタでサクラを使っています。 改行を含んだgrepはできますか? また、以下のやりかたを見ていただいて、良いやり方がありましたらご教示下さい。 ABCを含んだ行を対象に、;(行の終わり)までを抽出したいのです。 現在以下のような条件でgrepしていますが、ABCを含む行全てが抽出されません。 ABC.*(\r\n)*.*; また、以下のようにgrepすると、ABCを含む行全てがgrepされますが、対象ファイル内で改行されていた場合、;まで抽出されず、改行場所までしか抽出されません。 ABC; 詳しい方、宜しくお願い致します。

  • grepで40~70の数字をリストアップするコマンドを教えてください。

    grepで40~70の数字をリストアップするコマンドを教えてください。 1 2 3 4 5 ・ ・ ・ のように1~100まで改行して数字が書かれているテキストファイルがあります。 40 41 42 ・ ・ ・ 70 という様にgrepコマンドなどで40~70までを数字をリストアップするコマンドはないでしょうか?

  • sedコマンドの置換パターン条件について

    シェルスクリプトについて質問です。 /etc/ssh/sshd_configのAllowUsers行にユーザを追加&削除、sshdをリスタートするスクリプトを作っています。 ユーザ追加の処理はsedコマンドで実現できました。 sed -i -e "s/^AllowUsers/AllowUsers $USERNAME/" $CONF_FILE そして、悩んでいるのがユーザ削除時の処理です。 "AllowUsersで始まる行の中で" 且つ "変数$USERNAME" に一致する部分を削除するという処理です。sedは複数条件を指定することもできますが、以下記述の場合、2つの条件が独立して処理されてしまいます。 sed -e "s/^AllowUsers/AllowUsers/" -e "s/ $USERNAME//" $CONF_FILE ($USERNAMEに一致する部分はAllowUsersで始まらない行でも置換される) sedにAND条件のような使い方は可能でしょうか。 環境はCentOS 5.3、シェルはbashを使っています。 よろしくお願いいたします。

  • grepでの抽出について

    solarisでgrepを使ってログの抽出を行っているのですが、 123のある行を抽出したいとき、grep 123 ファイル名とすると 1234のある行も一緒に抽出されると思います。 これを123のみ抽出させる方法を教えてください。