2

私はこのようなコードを手に入れました:

lots of code... 
start(){
  some code...
  if mountpart "$1" /mnt -w ; then
  some code...
}
lots of code...

if mountpart "$1" /mnt -w ; thenを使用した後、新しいコードを挿入したいと思いsedます。複数回存在するためif mountpart "$1" /mnt -w ; then、一致するたびに新しいコードを追加することはできません。内部で最初に発生した後にのみ挿入する必要がありますstart() { }

これに使用するのは良い考えsedですか?または、そのような変更を実行するための適切なツールは何ですか?

4

4 に答える 4

2

状態の追跡を開始する必要がある場合(たとえば、ファイルのどこにいるのか、これまでに何を見たのか)、通常は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のように機能するようになります。各行を読み取って処理しますが、要求しない限り行を印刷しません。これにより、(おそらく)新しいコードを出力する前に、各行を出力できます。 -eperlにコマンドラインからプログラムを読み取らせます。プログラムを取得して再フォーマットし、コメントを追加すると、次のようになります。

// -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...'
于 2012-05-07T03:57:37.917 に答える
1

私のsedスクリプト、patch.sed:

# replace your "if then" block inside start() by another pattern 
# to make it unrecognizable to sed in the next command
/^start(){/,/^}/!{s/if mountpart "$1" \/mnt -w ; then/outside_start/g}

# inside start(), append "NEW CODE" after "if then" block
/if mountpart "$1" \/mnt -w ; then/a\
NEW CODE

# recover your "if then" block outside start()
/^start(){/,/^}/!{s/outside_start/if mountpart "$1" \/mnt -w ; then/g}

入力:

lots of code... 
if mountpart "$1" /mnt -w ; then
lots of code

start(){
  some code...
  if mountpart "$1" /mnt -w ; then
  some code...
}
lots of code...
if mountpart "$1" /mnt -w ; then

それを実行します:

sed -f patch.sed input

出力:

lots of code...
if mountpart "$1" /mnt -w ; then
lots of code

start(){
  some code...
if mountpart "$1" /mnt -w ; then
    NEW CODE
some code...
}
lots of code...
if mountpart "$1" /mnt -w ; then

「start(){」は1行の先頭にある必要があり、「}」もそれに一致します。これが、start()内で一致する方法です。

スクリプトがない場合は、「-e」オプションを使用して、sedによる複数の編集を実行できます。ただし、$をエスケープするように注意してください。

于 2012-05-07T05:28:17.097 に答える
1

これはあなたのために働くかもしれません:

sed '/^start()/,/^}/!b;x;/./{x;b};x;/if mountpart "$1" \/mnt -w ; then/!b;h;a\  NEWCODE' file

がたくさんある場合は、NEWCODEそれをファイルに入れて、代わりにこれを実行します。

sed '/^start()/,/^}/!b;x;/./{x;b};x;/if mountpart "$1" \/mnt -w ; then/!b;h;r newcode.txt' file

説明:

ホールドスペースはスペアレジスタです。テキストを操作するために、または(この場合のように)イベントがすでに発生したことを示すフラグ/スイッチとして使用できます。

  • テキストが間start()になく、}ベイルアウトする場合/^start()/,/^}/!b
  • ホールドスペースを確認し、そこに何かがある場合はベイルアウトしますx;/./{x;b}
  • マーカーを確認し、そうでない場合は救済しますx;/if mountpart "$1" \/mnt -w ; then/!b
  • 状態スイッチとしてマーカー文字列をホールドスペースに配置しますh
  • NEWCODE a\ NEWCODEまたはを追加/読むr newcode.txt
于 2012-05-07T08:53:35.623 に答える
0

TXR:

@(collect)
@prolog
@(until)
start(){
@(end)
@(collect)
@inner
@(until)
  if mountpart "$1" /mnt -w ; then
@(end)
@(collect)
@epilog
@(end)
@(output)
@{prolog "\n"}
@{inner "\n"}
@{epilog[0]}
NEW TEXT
@{epilog[1..t] "\n"}
@(end)

データ:

lots of code... 
  if mountpart "$1" /mnt -w ; then
lots of code

start(){
  some code...
  if mountpart "$1" /mnt -w ; then
  some code...
}
lots of code...
  if mountpart "$1" /mnt -w ; then

走る:

$ txr insert.txr code.sh
lots of code... 
  if mountpart "$1" /mnt -w ; then
lots of code

start(){
  some code...
  if mountpart "$1" /mnt -w ; then
NEW TEXT
  some code...
}
lots of code...
  if mountpart "$1" /mnt -w ; then
于 2012-05-07T04:57:34.780 に答える