Bash 使用sed进行多行替换

Bash 使用sed进行多行替换,bash,sed,makefile,sequelize.js,Bash,Sed,Makefile,Sequelize.js,由于实用程序中有一个bug,我需要找到一系列行并修改它们。我一直在尝试使用sed,但无法理解macOS上的语法 基本上,我需要找到以下几行: type: DataTypes.DATE, allowNull: true, primaryKey: true 。。。如果存在此序列,则更改最后两行: type: DataTypes.DATE, allowNull: true 整个文件最初看起来如下所示: /* jshint indent: 2 */ module.exports = functio

由于实用程序中有一个bug,我需要找到一系列行并修改它们。我一直在尝试使用
sed
,但无法理解macOS上的语法

基本上,我需要找到以下几行:

type: DataTypes.DATE,
allowNull: true,
primaryKey: true
。。。如果存在此序列,则更改最后两行:

type: DataTypes.DATE,
allowNull: true
整个文件最初看起来如下所示:

/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('product', {
    id: {
      type: DataTypes.BIGINT,
      allowNull: false,
      primaryKey: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      primaryKey: true
    },
    _u: {
      type: DataTypes.BIGINT,
      allowNull: false,
      references: {
        model: 'user',
        key: 'id'
      }
    },
    _v: {
      type: DataTypes.DATE,
      allowNull: false
    },
    _d: {
      type: DataTypes.DATE,
      allowNull: true,
      primaryKey: true
    }
  }, {
    tableName: 'product'
  });
};

对于sed中的多行模式匹配,您需要使用
N
命令将下一行拉入模式空间。如果我理解您的要求,那么类似这样的事情应该会起作用:

$ cat multiline-replace.sed 
/type: DataTypes.DATE,/{N
    /allowNull: true/{N  
       /primaryKey: true/{
         s/allowNull: true/why would I allow this?/
         s/primaryKey: true/shmimaryKey: false/
       }      
    }
}
其思想是当
/type:DataTypes.DATE,/
匹配时,将下一行读入模式空间(范围由{}分隔)。在
allowNull:true
行和
primaryKey:true
行上执行相同的操作。然后,在模式空间中有三行,您可以对它们进行修改。
s/pattern/replacement/

我将您的输入复制到文件
input
中,然后针对该程序对其进行了测试:

$ cat input | sed -f multiline-replace.sed 
/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('product', {
    id: {
      type: DataTypes.BIGINT,
      allowNull: false,
      primaryKey: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      primaryKey: true
    },
    _u: {
      type: DataTypes.BIGINT,
      allowNull: false,
      references: {
        model: 'user',
        key: 'id'
      }
    },
    _v: {
      type: DataTypes.DATE,
      allowNull: false
    },
    _d: {
      type: DataTypes.DATE,
      why would I allow this?,
      shmimaryKey: false
    }
  }, {
    tableName: 'product'
  });
};
$

另请参阅有关Unix堆栈交换的这篇文章,其中提供了有关sed命令的更多详细信息(还有
mansed
是您的朋友):

对于sed中的多行模式匹配,您需要使用
N
命令将下一行拉入模式空间。如果我了解您的要求,类似这样的操作应该是:

$ cat multiline-replace.sed 
/type: DataTypes.DATE,/{N
    /allowNull: true/{N  
       /primaryKey: true/{
         s/allowNull: true/why would I allow this?/
         s/primaryKey: true/shmimaryKey: false/
       }      
    }
}
其思想是当
/type:DataTypes.DATE,/
匹配时,将下一行读入模式空间(范围由{}分隔)。在
allowNull:true
行和
primaryKey:true
行上执行相同的操作。然后,在模式空间中有三行,您可以对它们进行修改。
s/pattern/replacement/

我将您的输入复制到文件
input
中,然后针对该程序对其进行了测试:

$ cat input | sed -f multiline-replace.sed 
/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('product', {
    id: {
      type: DataTypes.BIGINT,
      allowNull: false,
      primaryKey: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      primaryKey: true
    },
    _u: {
      type: DataTypes.BIGINT,
      allowNull: false,
      references: {
        model: 'user',
        key: 'id'
      }
    },
    _v: {
      type: DataTypes.DATE,
      allowNull: false
    },
    _d: {
      type: DataTypes.DATE,
      why would I allow this?,
      shmimaryKey: false
    }
  }, {
    tableName: 'product'
  });
};
$

另请参阅Unix堆栈交换上的这篇文章,其中提供了有关sed命令的更多详细信息(还有
man sed
是您的朋友):

在使用sed一段时间后,我再也记不起语法,创建了一个名为的实用程序,以一劳永逸地解决这个问题。尽管我已经选择了“正确的”答:几年前,为了完整起见,我把它贴在这里。以下是我使用的步骤

首先,安装它(我更喜欢全局安装)

npm i-g文件行替换器

…然后,只需运行一个命令(此示例用于上面的sequelize问题)


上面的命令将调整存在旧行的每个文件,并在修改之前创建一个备份。

在使用sed一段时间后,我再也记不起语法,创建了一个名为的实用程序,以一次性解决问题。尽管我已经选择了“正确的”答:几年前,为了完整起见,我把它贴在这里。以下是我使用的步骤

首先,安装它(我更喜欢全局安装)

npm i-g文件行替换器

…然后,只需运行一个命令(此示例用于上面的sequelize问题)


上面的命令将调整存在旧行的每个文件,并在修改之前创建一个备份。

您需要使用sed还是可以使用其他类似perl的东西,它几乎与正则表达式一样紧凑?在这一点上,我不在乎。我尝试了两种方法都没有成功。我猜我把正则表达式搞砸了。
sed
附带可以用于解决问题的堆栈缓冲区,但一般来说,
sed
很难用于多行问题。您需要使用sed还是可以使用其他类似于perl的东西,它对正则表达式几乎同样紧凑?在这一点上,我不在乎。我两种方法都尝试了,但都没有成功。我猜我把正则表达式搞砸了。
sed
comes有一个堆栈缓冲区,你可以用它来解决你的问题,但一般来说,
sed
很难用于多行问题。你有没有可能在这一个问题上使用你的上帝般的能力…哈哈,我来看看。但是,fwiw,当你在做复杂的多行事情时,升级到一个功能齐全的程序通常比较容易(和高级)编程语言(python或perl).干杯!你完全正确。想一想,我只是在替换一条只会出现一次的线。忘了我说了什么。你仍然是男人。你有没有可能在这条线上使用你的上帝般的力量…哈哈,我来看看。但是,fwiw,当你在做复杂的、多线的事情时,升级到全f通常比较容易eatured(和高级)编程语言(python或perl)。干杯!你完全正确。想想看,我只是在替换一行只会出现一次的代码。忘了我说了什么。你还是那个人。