状態の追跡を開始する必要がある場合(たとえば、ファイルのどこにいるのか、これまでに何を見たのか)、通常はsedからperlに切り替えます。必要なことを実行するための簡単なワンライナーを次に示します(「NEWCODE」を挿入する必要のある新しいコードに置き換えます。<filename>
実際のファイルに置き換えます)。
perl -ne 'BEGIN{$state=0} print; if (/^\s*start\(\){/) {$state++;} if (/if mountpart "\$1" \/mnt -w ; then/) { if ($state==1) {print "NEW CODE\n"; $state++;} }' <filename>
それを簡単に分解 -n
すると、perlがsedのように機能するようになります。各行を読み取って処理しますが、要求しない限り行を印刷しません。これにより、(おそらく)新しいコードを出力する前に、各行を出力できます。 -e
perlにコマンドラインからプログラムを読み取らせます。プログラムを取得して再フォーマットし、コメントを追加すると、次のようになります。
// -n runs the program for every line of input
// but a BEGIN {} block only runs once, before input
BEGIN {
//where are we in the input?
// 0=no start() yet
// 1=start() was seen
// 2=we have output the new code; never do it again
$state=0
}
print; // print the line we just read in, unchanged
if (/^\s*start\(\){/) { //regex. Did we see start(){ ?
$state++; //if so, change to next state
}
if (/if mountpart "\$1" \/mnt -w ; then/) { //regex. did we see mountpart cmd?
if ($state==1) { //if so, are we in the right state
print "NEW CODE\n"; //if so, output the new code
$state++; //...and change to next state
//...so we don't output new code 2x
}
}
ここでは、行を名前で参照することは決してないことに注意してください...行を印刷するために「print」と言うだけで、正規表現はsed paternのように見え、行と一致していると想定します。-n
これは、各行をperlの変数に読み込むため$_
です。これは、printなどの関数のデフォルトの引数です。これは私が大規模なperlプログラムを書く方法ではありませんが、このような1つのライナーまたは簡単な1回限りの修正スクリプトには適切です(そして慣用的です)。
<filename>
sedと同じように、を省略して入力をストリーミングすることもできます。例:
cat myfile.txt | perl -ne 'BEGIN...'