ここで、使用できる過去の質問を見つけようとしていますが、残念ながら、私のケースにぴったり合うものは見つかりません。
別のコマンドの出力から次のようなものを取得したいと思います。
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
一致する行pattern
とc=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でない場合は次の行を追加します
- 改行の後に数字がある場合(より具体的に指定できます)、
b
ranch 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