sedを使用して大容量ファイルのテキストを置き換える

sedを使用して大容量ファイルのテキストを置き換える

渡された正規表現に基づいて置き換えられるテキストを含む大容量ファイルがあります。正規表現をテストして一致するパターンを見つけることができますが、それを使用するときにsed代替テキストはありません。ちなみに私の環境はWindows 16GBメモリで、ファイルサイズは14GB程度になる点を参考にしてください。

sed -i "/,[\r\n]+  CONSTRAINT `[a-zA-Z0-9_]+` FOREIGN KEY \(`[a-zA-Z0-9_]+`\) REFERENCES `[a-zA-Z0-9_]+` \(`[a-zA-Z0-9_]+`\)/ s// /g" all_files_test.sql

cmd.exe(上記はUnixシェルではなくコマンドラインであることに注意してください。)

all_files_test.sql文書:

DROP TABLE IF EXISTS `holdings_FLZWHX`;
;
;
CREATE TABLE `holdings_FLZWHX` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `DateAdded` datetime NOT NULL,
  `FundId` int(11) NOT NULL,
  `AssetId` int(11) NOT NULL,
  `DayChangeEqt` decimal(18,2) DEFAULT NULL,
  `PMinDayRet` decimal(18,2) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `holdings_FLZWHX_FundId` (`FundId`),
  KEY `holdings_FLZWHX_AssetId` (`AssetId`),
  KEY `holdings_FLZWHX_TypeId` (`TypeId`),
  KEY `holdings_FLZWHX_TickerId` (`TickerId`),
  KEY `holdings_FLZWHX_StyleId` (`StyleId`),
  KEY `holdings_FLZWHX_SectorId` (`SectorId`),
  KEY `holdings_FLZWHX_CountryId` (`CountryId`),
  KEY `holdings_FLZWHX_CurrencyId` (`CurrencyId`),
  CONSTRAINT `holdings_FLZWHX_ibfk_1` FOREIGN KEY (`FundId`) REFERENCES `target_funds` (`fundid`),
  CONSTRAINT `holdings_FLZWHX_ibfk_2` FOREIGN KEY (`AssetId`) REFERENCES `asset` (`id`),
  CONSTRAINT `holdings_FLZWHX_ibfk_3` FOREIGN KEY (`TypeId`) REFERENCES `type` (`id`),
  CONSTRAINT `holdings_FLZWHX_ibfk_4` FOREIGN KEY (`TickerId`) REFERENCES `ticker` (`id`),
  CONSTRAINT `holdings_FLZWHX_ibfk_5` FOREIGN KEY (`StyleId`) REFERENCES `style` (`id`),
  CONSTRAINT `holdings_FLZWHX_ibfk_6` FOREIGN KEY (`SectorId`) REFERENCES `sector` (`id`),
  CONSTRAINT `holdings_FLZWHX_ibfk_7` FOREIGN KEY (`CountryId`) REFERENCES `country` (`id`),
  CONSTRAINT `holdings_FLZWHX_ibfk_8` FOREIGN KEY (`CurrencyId`) REFERENCES `currency` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4201 DEFAULT CHARSET=latin1;
;

私が期待する結果は次のとおりです。

DROP TABLE IF EXISTS `holdings_FLZWHX`;
;
;
CREATE TABLE `holdings_FLZWHX` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `DateAdded` datetime NOT NULL,
  `FundId` int(11) NOT NULL,
  `AssetId` int(11) NOT NULL,
  `DayChangeEqt` decimal(18,2) DEFAULT NULL,
  `PMinDayRet` decimal(18,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4201 DEFAULT CHARSET=latin1;
;

ベストアンサー1

  1. テストされた正規表現基本と拡張正規表現だけでなく、非標準スタイルも多く、その一部を使用しているので難しい説明です。

  2. sed拡張正規表現を使用しています。 withオプションを教えてください。-E

  3. パターンで改行(キャリッジリターン、改行)を探していますが、入力を1行sedずつ処理するため、行を連結しないと一致しません。ただし、GNUを使用しているように見えるため、すべての行を一度に処理するオプションがsedあります。-zこれは例では機能しますが、大容量ファイルでは失敗する可能性があります。

  4. シェルによっては、スクリプトを保護するために二重引用符の代わりに一重引用符を使用する必要があります。

    sed -zEi '/,[\r\n]+ 制約[a-zA-Z0-9_]+外部キー( [a-zA-Z0-9_]+) 参照[a-zA-Z0-9_]+( [a-zA-Z0-9_]+)/ s// /g' all_files_test.sql

あなたが期待した代替タスクを実行し、zshおそらくあなたのタスクも実行したかもしれませんcmd.exe。それでも、行アドレスはバッファ内のすべての行に対して意味がありません。

sed -zEi 's/,[\r\n]+  CONSTRAINT `[a-zA-Z0-9_]+` FOREIGN KEY \(`[a-zA-Z0-9_]+`\) REFERENCES `[a-zA-Z0-9_]+` \(`[a-zA-Z0-9_]+`\)/ /g' all_files_test.sql

より論理的です(結果は同じままです)。最後に、線がどのようにKEY `holding消えるのか説明しませんでした。

ただし、複数行を置き換える標準的な方法があり、このN;P;Dパターンは大容量ファイルでも機能します。

sed -Ei 'N;/,*[\r\n]+  CONSTRAINT `[a-zA-Z0-9_]+` FOREIGN KEY \(`[a-zA-Z0-9_]+`\) REFERENCES `[a-zA-Z0-9_]+` \(`[a-zA-Z0-9_]+`\)/{s// /g;s/^/\n/;D;};P;D' all_files_test.sql

Nパターンが一致するように、常に次の行を追加してください。Pバッファの最初の行を印刷し、D最初の行を削除して残りの行から再開します。したがって、N;P;Dパターン空間には常に一対の線がある。

ただし、置き換える場合は1行しかありませんが、次の行を続行したいので、パターンの先頭に空白行s/^/\n/(GNUのみ)を挿入してに置き換えることをお勧めします。sedD

おすすめ記事