• 締切済み

sedで特定文字が出たら次の行は読み飛ばす

Linuxのsedコマンドなのですが、特定文字列が出たら読み飛ばすという事をやっています。 例えば、'#SKIP'が出たら次の行(複数行)は読み飛ばすみたいな事をです。 行飛ばしで2点質問がありますのでお願いします。 以下の様なファイルがあります。 /---------- $ cat input.txt YYYY YYYY YYYY YYYY YYYY #SKIP YYYY YYYY YYYY YYYY YYYY -----------/ '#SKIP'が出たら次の行を読み飛ばすは、 $ sed '/#SKIP/{N; s/YYYY/2016/g}' input.txt YYYY YYYY YYYY YYYY YYYY #SKIP 2016 YYYY YYYY YYYY YYYY と、'#SKIP'の下の行が置換されます。 数行読み飛ばす場合は $ sed '/#SKIP/{N;N;N; s/YYYY/2016/g}' input.txt YYYY YYYY YYYY YYYY YYYY #SKIP 2016 2016 2016 YYYY YYYY と、'#SKIP'から下の3行が置換されます。 てっきり、'#SKIP'から指定した(N;)行分読み飛ばし、それ以降を置換すると 思っていたのですが違うのでしょうか。 使い方が間違っているのでしょうか。 また、同じ様な行飛ばしで、範囲指定した場合ですが、 $ sed -e '3,20n;n;n; s/YYYY/2016/g' input.txt や $ sed -e '3,20{n;n;n; s/YYYY/2016/g}' input.txt とした場合、範囲指定外の3~20以外でも置換されます。 3行目から置換されたり、20行目を越えても置換されます。 OS、バージョンによるものでしょか。 本記載の2点について教えて下さい。

みんなの回答

  • trapezium
  • ベストアンサー率62% (276/442)
回答No.4

既に余談ですが、混乱させたままでは申し訳ないので、 > snipという見慣れないコマンド? > なのですが、どういうものなのですか。 いえ、これは単に引用を切り詰めた、ちょん切ったという英単語の意味そのまま、もしくはマークみたいなものです。昔から ML や Usenet, BBS などのスレッドで良く使います。

abc999xyz
質問者

お礼

ありがとうございます。

  • trapezium
  • ベストアンサー率62% (276/442)
回答No.3

> 範囲指定だからてっきり指定した3行目から20行目までの間でしか > 見て置換するものだと思っていましたが、指定した範囲の条件次第 > では、範囲を超えても置換されるのですね。 interactive なエディタのリージョン指定みたいに、オブジェクト指向的な動作ではありません。途中で q するかエラーでもしない限り、入力の 1行目から EOF まで1行づつ処理されます。n や N はそれを意識して行うわけですから、その制御は使う側にあります。 > 範囲を超えているからと言ってとめてくれるのではないのですね。 止めたければ、n/N したあと行番号はカウントアップされてますから 3,20s/YYYY/2016/g とすれば置換は実行されません。 > 例えば snip > それ以降は範囲外となるので、11行目以降は置換がないと > いうことになるのですね。 そうなります。

abc999xyz
質問者

お礼

補足、説明ありがとうございます。 >> 例えば > snip snipという見慣れないコマンド? なのですが、どういうものなのですか。 sedを使用したり、調べたりしても見かけないですが。

abc999xyz
質問者

補足

お礼遅くなってすみません。 > 止めたければ、n/N したあと行番号はカウントアップされてますから > 3,20s/YYYY/2016/g > とすれば置換は実行されません。 再度、範囲指定できること知りませんでした。 勉強になりました。

  • trapezium
  • ベストアンサー率62% (276/442)
回答No.2

> 3行目から置換されたり、20行目を越えても置換されます。 補足しとくと > $ sed -e '3,20n;n;n; s/YYYY/2016/g' input.txt > 1.YYYY > 2.YYYY > 3.2016 1行目では 3,20n はスキップして、n;n; で3行目を読み s で置換してるので > 4.YYYY > 5.YYYY > 6.YYYY > 7.2016 そこから 20 までの範囲では n;n;n と三行飛す格好になるので、3行置きに置換される。そのあとは 2行置きに戻るはず > $ sed -e '3,20{n;n;n; s/YYYY/2016/g}' input.txt > 6.2016 > 10.2016 > 14.2016 > 18.2016 > 22.2016 これはそれぞれ >> 実際は、3nnn7nnn11nnn15nnn19nnn の三つめの n のあとで s されるから 19+3 だね

abc999xyz
質問者

お礼

補足ありがとうございます。 自分の認識が間違っていたのが分かりました。 範囲指定だからてっきり指定した3行目から20行目までの間でしか 見て置換するものだと思っていましたが、指定した範囲の条件次第 では、範囲を超えても置換されるのですね。 範囲を超えているからと言ってとめてくれるのではないのですね。 例えば $ sed -e '3,10{n;n;n; s/YYYY/2016/g}' input.txt だと 6.2016 10.2016 が置換されます。 これだと、 3nnn7nnn の三つめの n のあとで s されるから 7+3 で 10 となり、 それ以降は範囲外となるので、11行目以降は置換がないと いうことになるのですね。

  • trapezium
  • ベストアンサー率62% (276/442)
回答No.1

> てっきり、'#SKIP'から指定した(N;)行分読み飛ばし、それ以降を置換すると > 思っていたのですが違うのでしょうか。 N は次の行をパターンスペースに追加です。読み飛ばしじゃありません。N した段階でパターンスペースの内容は #SKIP YYYY となっているので、次の s で YYYY が 2016 に置換されてます。で -n が指定されてなければ結果が出力されます。 > $ sed -e '3,20n;n;n; s/YYYY/2016/g' input.txt は最初の n だけが 3,20 で、そこから後ろは全ての行対象なので当然でしょう? > $ sed -e '3,20{n;n;n; s/YYYY/2016/g}' input.txt 少くとも 20 から n,n,n してる分あとの行を s してますから、その意味では読み飛ばしてますね。実際は、3nnn7nnn11nnn15nnn19nnn ってなるから 20 では実行さないはずですが。

abc999xyz
質問者

お礼

ありがとうございます。 >N は次の行をパターンスペースに追加です。読み飛ばしじゃありません。N した段階でパターンスペースの内容は 行の読み飛ばしではないのですね。 検索したとき、行の読み飛ばしとあったので、てっきり読み飛ばしてくれるものだと。 確かに、manコマンドで 「n N 入力の次の行をパターンスペースに読み込む/追加する。」 と書かれています。 > $ sed -e '3,20n;n;n; s/YYYY/2016/g' input.txt > は最初の n だけが 3,20 で、そこから後ろは全ての行対象なので当然でしょう? > > $ sed -e '3,20{n;n;n; s/YYYY/2016/g}' input.txt ですか、以下の様なファイルで試してみました。 3行目から置換されたり、20行目を越えても置換されます。 $ cat input.txt 1.YYYY 2.YYYY 3.YYYY 4.YYYY 5.YYYY 6.YYYY 7.YYYY 8.YYYY 9.YYYY 10.YYYY 11.YYYY 12.YYYY 13.YYYY 14.YYYY 15.YYYY 16.YYYY 17.YYYY 18.YYYY 19.YYYY 20.YYYY 21.YYYY 22.YYYY 23.YYYY 24.YYYY 25.YYYY > $ sed -e '3,20n;n;n; s/YYYY/2016/g' input.txt $ sed -e '3,20n;n;n; s/YYYY/2016/g' input.txt 1.YYYY 2.YYYY 3.2016 4.YYYY 5.YYYY 6.YYYY 7.2016 8.YYYY 9.YYYY 10.YYYY 11.2016 12.YYYY 13.YYYY 14.YYYY 15.2016 16.YYYY 17.YYYY 18.YYYY 19.2016 20.YYYY 21.YYYY 22.YYYY 23.2016 24.YYYY 25.YYYY > $ sed -e '3,20{n;n;n; s/YYYY/2016/g}' input.txt $ sed -e '3,20{n;n;n; s/YYYY/2016/g}' input.txt 1.YYYY 2.YYYY 3.YYYY 4.YYYY 5.YYYY 6.2016 7.YYYY 8.YYYY 9.YYYY 10.2016 11.YYYY 12.YYYY 13.YYYY 14.2016 15.YYYY 16.YYYY 17.YYYY 18.2016 19.YYYY 20.YYYY 21.YYYY 22.2016 23.YYYY 24.YYYY 25.YYYY