web-dev-qa-db-ja.com

複数行Sed置換

次のテキスト(ちなみに、MySQLダンプの一部)について考えてみます。

 CREATE TABLE `table`(
` id` int(10)NOT NULL auto_increment、
 `name` varchar(100)NOT NULL default ''、
 `description` text NOT NULL、
 PRIMARY KEY(` id`)、
 FULLTEXT KEY `full_index`(` name`)
)ENGINE = MyISAM DEFAULT CHARSET = latin1; 
/*!40101 SET character_set_client = @saved_cs_client * /; 

FULLTEXTキーを削除したいのですが、SQLが有効なままになるように、上の行の末尾のコンマも削除したいと思います。

誰かがこれを行うためのsedレシピを思い付く(そして説明する)ことができますか?

6
Craig Watson

AWK回答

sqlという名前のファイルにサンプルテキストがある場合、次のパターン(わかりやすくするために改行とインデントを使用):

awk -v skip=1 '{
    if (skip) { skip=0 }
    else {
        if (/FULLTEXT KEY/) { skip=1; sub(/,$/, "", prevline) }
        print prevline
    }
    prevline=$0
}
END { print prevline }' sql

生成:

CREATE TABLE `table` (
  `id` int(10) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL default '',
  `description` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

説明:

  • 現在の行を検査した後、すべての反復で以前検出された行のみを出力することにより、「先読み」を実装します。
  • 現在の行にFULLTEXT KEYマーカーが含まれている場合、次の反復中にこの行の印刷をスキップするフラグを設定します。また、印刷される直前の行の末尾のカンマも削除します。
  • 最初にprevline1( "true")に設定することにより、(skipが設定される前の)空の最初の行の印刷をスキップします。
  • スクリプトを追加のprevline printで終了して、最後の行を印刷してください。現在の実装では、この最後の行がスキップされるリスクのない行であると想定していることに注意してください。つまり、FULLTEXT KEYマーカーが含まれていません。

元の(不完全)sed回答

この回答は不完全であり、ほとんどの場合正しくありません。sedは、複数行のマッチングを行うと、意図した結果に対して入力ストリームをすぐに消費するためです-コメントで指摘されているように、機能するだけです偶数行の一致の場合!sedには「真の」先読み機能がないため、Python/Perl/etcなど、または実際には上記のAWKを使用したほうがよいでしょう。

sqlという名前のファイルにサンプルテキストがある場合、次のパターンになります。

$ sed 'N; s/,\n  FULLTEXT.*//' sql

生成:

CREATE TABLE `table` (
  `id` int(10) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL default '',
  `description` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

説明:

  • Nは、複数行のマッチングを有効にします。
  • \nは改行を表します。
  • s/pattern/replacement/は標準の置換構文です。
  • .*は、現在の行の末尾に一致します。
10

Sedで2行を管理することはそれほど難しくありません。
パターンスペースに2行入れてください。

  • $!N:このコマンドは、パターンスペースに行を追加します。
  • P:パターンスペースの最初の行を印刷します
  • D:パターン空間の最初の行を削除し、新しいサイクルを開始します(行を読み取らずに)
    1行しか残っていない場合は、「d」コマンドのように動作します(つまり、行を読み取って新しいサイクルを開始します)
sed -n '$!N; s/,[[:space:]]*FULLTEXT KEY.*// ;P;D' 
0
mug896