使用awk或sed根据模式匹配添加一条线

使用awk或sed根据模式匹配添加一条线,awk,sed,find-replace,Awk,Sed,Find Replace,A有一个包含SQL迁移命令的文件。比如说 // admin_setting $this->createTable('{{%admin_setting}}', [ 'setting_id' => Schema::TYPE_INTEGER . "(11) NOT NULL AUTO_INCREMENT", 'short_description' => Schema::TYPE_STRING . "(255) NOT NULL", 'value' =>

A有一个包含SQL迁移命令的文件。比如说

// admin_setting
$this->createTable('{{%admin_setting}}', [
    'setting_id' => Schema::TYPE_INTEGER . "(11)  NOT NULL AUTO_INCREMENT",
    'short_description' => Schema::TYPE_STRING . "(255) NOT NULL",
    'value' => Schema::TYPE_TEXT . " NULL",
    'PRIMARY KEY (setting_id)',
], $this->tableOptions);

// authorization
$this->createTable('{{%authorization}}', [
    'authorization_id' => Schema::TYPE_INTEGER . "(11)  NOT NULL AUTO_INCREMENT",
    'short_description' => Schema::TYPE_STRING . "(255) NULL",
    'PRIMARY KEY (authorization_id)',
], $this->tableOptions);
我想在包含“createTable()命令”的行之前添加另一个命令,以便我的示例文件如下所示:-

// admin_setting
$this->dropTable('{{%admin_setting}}');
$this->createTable('{{%admin_setting}}', [
    'setting_id' => Schema::TYPE_INTEGER . "(11)  NOT NULL AUTO_INCREMENT",
    'short_description' => Schema::TYPE_STRING . "(255) NOT NULL",
    'value' => Schema::TYPE_TEXT . " NULL",
    'PRIMARY KEY (setting_id)',
], $this->tableOptions);

// authorization
$this->dropTable('{{%authorization}}');
$this->createTable('{{%authorization}}', [
    'authorization_id' => Schema::TYPE_INTEGER . "(11)  NOT NULL AUTO_INCREMENT",
    'short_description' => Schema::TYPE_STRING . "(255) NULL",
    'PRIMARY KEY (authorization_id)',
], $this->tableOptions);
我看到了很多删除与模式匹配的行的示例,但到目前为止,没有一个可以让我得到上述更改

最近的一次是

   awk '/createTable/{print "$this->DropTable();"}1' file
但我无法填写括号内的内容。

这可能适合您(GNU-sed):

复制包含
createTable
的行,然后在第一次出现时附加复制的行和模式匹配并替换。

这可能适用于您(GNU-sed):


复制包含
createTable
的行,然后在第一次出现时附加复制的行和模式匹配并替换。

您可以在
awk
中使用字段分隔符。将其设置为单引号,您可以访问字段2中的所需值:

awk -F"'" '/createTable/{print "$this->dropTable('\''"$2"'\'');"}1'
sed的
s
也可用于:

sed 's/\$this->createTable(\('\''[^'\'']*'\''\)/$this->dropTable(\1);\n\0/'
转义单引号有点棘手。或者,您可以用双引号括住命令,但是,在这种情况下,您需要注意防止shell解释
$

sed "s/\\\$this->createTable(\('[^']*'\)/\$this->dropTable(\1);\n\0/"

您可以在
awk
中使用字段分隔符。将其设置为单引号,可以访问字段2中的所需值:

awk -F"'" '/createTable/{print "$this->dropTable('\''"$2"'\'');"}1'
sed的
s
也可用于:

sed 's/\$this->createTable(\('\''[^'\'']*'\''\)/$this->dropTable(\1);\n\0/'
转义单引号有点棘手。或者,您可以用双引号括住命令,但是,在这种情况下,您需要注意防止shell解释
$

sed "s/\\\$this->createTable(\('[^']*'\)/\$this->dropTable(\1);\n\0/"
GNU awk解决方案:

/createTable/ {
    match ($0, /createTable\('(.*)',/, x)
    print "$this->dropTable('" x[1] "');"
}

{
    print $0
}
编辑:使用建议,注意这是GNU awk,并从第一个块tks中删除了不需要的打印

注意:我认为整个{print$0}可能会被“1”(单个字符“1”)取代,但我认为可读性比这里的简短要好。

GNU awk解决方案:

/createTable/ {
    match ($0, /createTable\('(.*)',/, x)
    print "$this->dropTable('" x[1] "');"
}

{
    print $0
}
$ cat tst.awk
{ new = $0 }
sub(/createTable/,"dropTable",new) {
    sub(/,.*/,");",new)
    print new
}
{ print }

$ awk -f tst.awk file
// admin_setting
$this->dropTable('{{%admin_setting}}');
$this->createTable('{{%admin_setting}}', [
    'setting_id' => Schema::TYPE_INTEGER . "(11)  NOT NULL AUTO_INCREMENT",
    'short_description' => Schema::TYPE_STRING . "(255) NOT NULL",
    'value' => Schema::TYPE_TEXT . " NULL",
    'PRIMARY KEY (setting_id)',
], $this->tableOptions);

// authorization
$this->dropTable('{{%authorization}}');
$this->createTable('{{%authorization}}', [
    'authorization_id' => Schema::TYPE_INTEGER . "(11)  NOT NULL AUTO_INCREMENT",
    'short_description' => Schema::TYPE_STRING . "(255) NULL",
    'PRIMARY KEY (authorization_id)',
], $this->tableOptions);
编辑:使用建议,注意这是GNU awk,并从第一个块tks中删除了不需要的打印


注意:我认为整个{print$0}可能会被“1”(单个字符“1”)所取代,但我认为这里的可读性比简短要好。

对我来说效果很好。您介意花点时间解释h;G参数吗。@crafter使用
h
命令将当前行复制到称为保持空间(HS)的寄存器中。使用
G
命令将HS的内容附加到模式空间(PS)中,模式空间是保存当前行的寄存器。请参阅。这对我来说非常有用。您是否介意花时间解释h;G参数。@crafter使用
h
命令将当前行复制到一个称为保持空间(HS)的寄存器中.G命令将HS的内容附加到模式空间(PS)中,后者是保存当前行的寄存器。请参阅。两者都应该工作。它们只是在使用单引号或双引号方面有所不同。使用单引号版本,而不是跳入和跳出shell(顺便说一句,这就是您要做的,不是跳出单引号)只要在需要单个报价的任何地方使用转义序列
\047
,例如
打印“$this->dropTable(\047”$2”\047);“
。在这种情况下,您也可以使用
print”$this->dropTable(“FS$2fs”);“
。两者都应该有效。它们只是在单引号或双引号的使用上有所不同。使用单引号版本,而不是跳进和跳出shell(顺便说一句,这就是你要做的,不是转义单引号),只要在你想要单引号的任何地方使用转义序列就可以了,例如,
打印“$this->dropTable(\047”$2”\047);“
。在这种情况下,您也可以使用
print”$this->dropTable(“FS$2fs”);“
。请注意,这需要GNU awk用于三参数匹配()函数干式:从第一个块中删除
print$0;next
。注意,这需要GNU awk用于三参数匹配()函数干式:从第一个块中删除
print$0;next
$ cat tst.awk
{ new = $0 }
sub(/createTable/,"dropTable",new) {
    sub(/,.*/,");",new)
    print new
}
{ print }

$ awk -f tst.awk file
// admin_setting
$this->dropTable('{{%admin_setting}}');
$this->createTable('{{%admin_setting}}', [
    'setting_id' => Schema::TYPE_INTEGER . "(11)  NOT NULL AUTO_INCREMENT",
    'short_description' => Schema::TYPE_STRING . "(255) NOT NULL",
    'value' => Schema::TYPE_TEXT . " NULL",
    'PRIMARY KEY (setting_id)',
], $this->tableOptions);

// authorization
$this->dropTable('{{%authorization}}');
$this->createTable('{{%authorization}}', [
    'authorization_id' => Schema::TYPE_INTEGER . "(11)  NOT NULL AUTO_INCREMENT",
    'short_description' => Schema::TYPE_STRING . "(255) NULL",
    'PRIMARY KEY (authorization_id)',
], $this->tableOptions);