Text-Processing

刪除多行字元串

  • October 23, 2017

這裡有幾個關於使用 Unix shell 替換多行字元串的問題,但我還沒有找到一個可以在這種情況下工作的問題。

我正在嘗試從一些 MySQL DDL 中刪除鍵和約束,如下所示(一個範例):

CREATE TABLE `access_group` (
 `GROUP_ID` int(10) NOT NULL AUTO_INCREMENT,
 `PARENT_GROUP_ID` int(10) DEFAULT NULL,
 `GROUP_NAME` varchar(45) NOT NULL,
 `GROUP_DESC` varchar(45) NOT NULL DEFAULT '',
 PRIMARY KEY (`GROUP_ID`),
 KEY `testkey` (`PARENT_GROUP_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=latin1;

我想刪除從逗號結束’PRIMARY KEY’之前的行到但不包括’)ENGINE =‘的所有內容(這些之間可以有零行或多行,它們不會總是以KEY開頭或有括號,但 ‘) ENGINE=’ 是一致的)。結果應如下所示:

CREATE TABLE `access_group` (
 `GROUP_ID` int(10) NOT NULL AUTO_INCREMENT,
 `PARENT_GROUP_ID` int(10) DEFAULT NULL,
 `GROUP_NAME` varchar(45) NOT NULL,
 `GROUP_DESC` varchar(45) NOT NULL DEFAULT ''
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=latin1;

我願意使用任何標準的命令行實用程序(例如 sed、perl、awk),但由於這些文件可能相當大(有些文件大約為數十或數百 GB),因此它們需要高效。由於文件通常以 gzip 格式儲存(或者有時我直接處理 mysql 轉儲實用程序的輸出,而不是首先寫入磁碟),因此我需要可以通過管道輸入和輸出的東西。

保持狀態是否列印上一行,編輯表示在必要時刪除逗號。這種方法只在記憶體中保留一兩行文件。

#!/usr/bin/env perl
use strict;
use warnings;

my $printing = 1;
my $previous;

# reads from standard input (optionally with the conventional -) or from
# the named files
shift @ARGV if @ARGV == 1 and $ARGV[0] eq '-';
while ( my $line = readline ) {
   if ( $line =~ m/^\s+PRIMARY KEY/ ) {
       $previous =~ s/,[ \t]*$//;
       $printing = 0;
   } elsif ( $line =~ m/^\) ENGINE/ ) {
       $printing = 1;
   } elsif ( !$printing ) {
       undef $previous;
   }
   print $previous if defined $previous;
   $previous = $line if $printing;
}
# don't forget last line after fall off the end of input (eof)
print $previous if defined $previous;

使用ex(又名vimEx 模式):

ex +'%s/,\n *PRIM\_.*\ze\n) ENGINE//' +wq file

只是 Vim 替換刪除(空替換//)的“批處理”版本,它與 進行多行匹配\_.*並排除模式的最後部分 with \ze

這會就地修改文件。如果您不希望這樣做以保存到新文件file2

ex +'%s/,\n *PRIM\_.*\ze\n) ENGINE//' +'w file2' +q! file

**更新:**在文件中管道…這有點不尋常,/dev/stdin但可以解決問題:

cat file | ex +'%s/,\n *PRIM\_.*\ze\n) ENGINE//' +'%p|q!' /dev/stdin

引用自:https://unix.stackexchange.com/questions/399167