値が見つからない場合は、値を含む新しい行を挿入します

値が見つからない場合は、値を含む新しい行を挿入します

ここで、使用できる過去の質問を見つけようとしていますが、残念ながら、私のケースにぴったり合うものは見つかりません。

別のコマンドの出力から次のようなものを取得したいと思います。

pattern.d
17.91
17.55
pattern.b
pattern.a
7.21
9.34
pattern.c

これに:

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

もう少し詳しく説明します。文字列「pattern」を含むすべての行の後には常に数字がなければなりません。そうでない場合は、値 1000 の新しい行を挿入します。

パターンにはさまざまな「拡張子」(.a .b .c .d ですが、「拡張子」には数字は含まれません)があり、後で内容をアルファベット順に並べ替えるのに役立つことに注意してください。

編集: 回答は受け入れましたが、別のバリエーションを探している人がいる場合に備えて、「パターン」の出現はさまざまであり、次のように 2 つまたは 3 つ以上連続して出現する可能性があることを明記する必要があります。

pattern.a
pattern.d
pattern.c
pattern.d
pattern.b
17.91

答え1

これは、任意の入力(たとえば、一致する複数の連続した行)sedで機能するソリューションです。pattern

sed '1{                   # when on first line
x                         # exchange
s/^/1000/                 # replace the empty hold buffer with "1000"
x                         # exchange back
}
: do                      # label "do"
/pattern/{                # if the current line matches "pattern"
${                        # if we're on the last line
G                         # append hold buffer content to pattern space
b                         # go to end of script
}
n                         # otherwise print and pull in the next line
/^[[:digit:]]/!{          # if this one doesn't start with a digit
x                         # exchange
p                         # print (the pattern space is now "1000")
x                         # exchange back
b do                      # go to label "do"
}
}' infile

次のようgnu sedに書くことができる。

sed '1{x;s/^/1000/;x};:b;/pattern/{${G;b};n;/^[[:digit:]]/!{x;p;x;bb}}' infile

同様のことを次のように実行できますawk:

awk -vc=0 '!/^[[:digit:]]/{
if (c) {print "1000"}
}
{ if (/pattern/){c=1} else{c=0}
}
END{if (c){print "1000"}
};1' infile

つまり、c=1一致する行patternc=0残りの行、および数字で始まらない各行 (およびブロック内END)で がc設定されているか (または1、前の行が と一致するかpattern) を確認し、設定されている場合は を印刷します1000

答え2

sed -e '
   $!{
      /pattern\.[a-z]/N
      /\n/!b
      /\n[+-]\{0,1\}[.][0-9]\{1,\}$/b
      /\n[+-]\{0,1\}[0-9]\{1,\}\([.][0-9]*\)\{0,1\}$/b
      h;s/\(.*\n\).*/\11000/p
      g;D
   }
   /pattern\.[a-z]/a\
1000
' yourfile

結果

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

働く

  • eof にいない間は、$!{...}現在の行が対象の行であるという条件で、次の行をパターン スペースに追加します。
  • 次に、次の場合にはそれ以上の処理をスキップします。a) 改行が見つからない => 現在の行にパターンがない。b) 2 行目に .nnn 形式の浮動小数点数がある。c) 2 行目にのみ mmm、mmm.、または mmm.nnn 形式の浮動小数点数が見つかる。d) いずれの可能性もない場合 => 改行後の次の行の末尾にマジックナンバー 1000 を追加する必要がある。

答え3

の連続するインスタンスが 2 つ以上存在せずpattern、GNU sed を使用している場合は、次のようになります。

sed '/^pattern/ {$!N; /\n[0-9]/b; s/$/\n1000/M}' file
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

使い方:

  • 現在の行がで始まるpattern場合
    • EOFでない場合は次の行を追加します
    • 改行の後に数字がある場合(より具体的に指定できます)、branch out(つまり、次の行に進みます); そうでない場合
    • 最初の行を改行で終わらせ、1000

GNU 固有のM修飾子を使用すると、 または のいずれかに一致させることができるため$、「通常」の場合と、後続の行が追加されない EOF の場合の両方を処理できます。\n$

答え4

awk解決:

awk '{ if ($0 ~ /pattern/) {      # if it's a `pattern` line
         if ((getline nl) > 0) {  # check if next record exists
             # if next record hasn't number - insert `1000`, otherwise - print current and next records as they are
             print ((nl !~ /^[0-9]/)? $0 ORS 1000 ORS nl: $0 ORS nl)
         } else {
             print $0 ORS 1000   # if the file ends up with pattern - insert `1000`
         } 
       } else {
          print $0  # print other record
       }
    }' file

出力:

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

関連情報