【问题标题】:Replace all hyphens before the first bracket within a file替换文件中第一个括号之前的所有连字符
【发布时间】:2017-06-04 07:03:27
【问题描述】:

我正在尝试使用 sed 或 perl 来替换 ); 的第一个实例之前文件中出现的所有连字符;

到目前为止,我有以下内容替换了我的文件中的所有连字符,但我不能让它只匹配“);”的第一个实例。

perl -pi -e 's/[^.*);]?-/_/' 00-90.sql

更多信息:

我正在尝试从已生成的创建表 SQL 中删除无效的连字符,我们有 1k+ 个文件要通过,但我用它点击的任何内容都会替换所有连字符。

要清理的文本示例:

CREATE TABLE e_00_90 (
Last_Name nvarchar(50),
  Initials nvarchar(3),
  Company_Division nvarchar(50),
  Status nvarchar(12),
  Ckeyword5 nvarchar(15),
  Value_of_Contract_-_Overh decimal(20,2)
);
insert into export_00_90 values ('Sample-One', 'R', 'Div 1', 'Expired', 'ANONYTR', 5000);
insert into export_00_90 values ('Sample Two', 'R', 'Div_2', 'Expired', 'WISHBONE', 13000);

我只需要 Create Table 块来删除连字符。

【问题讨论】:

  • 试试's/^((?:(?!\);).)*)-\);/$1_);/'

标签: regex perl sed pattern-matching


【解决方案1】:

[编辑]
使用 awk:

awk -v RS=');' -v ORS=');' '/^CREATE TABLE/{gsub("-","_")}1'

使用 perl:

perl -pe'BEGIN{$/=");"} /^CREATE TABLE/&&y/-/_/'

使用 sed:

sed '/^CREATE TABLE/{:;/);/!{N;b};y/-/_/;}'

awk 和 perl 方式是一样的,都是使用记录分隔符);,检查这个是否以“CREATE TABLE”开头,并将每个连字符翻译成下划线。

sed 版本并没有太大的不同,只是您需要自己构建文本块,将每一行追加到);(请注意,这种方式假定同一行中); 之后没有更多代码)

{
  :  # define an empty label
  /);/! # if ); doesn't match
  {
    N # append a newline to the pattern space
    b # go to the label
  }
  y/-/_/ # translate
}

[旧答案:仅适用于行]
使用 sed:

sed -E ':;s/^(([^)-]|\)[^;-])*\)*)-/\1_/;t'

或使用 perl:

perl -pe's/.*?\);|.+/$&=~y|-|_|r/e'

(这种方式匹配所有直到第一个); 或字符串结尾,然后匹配中的每个连字符都使用y/// 转换为下划线)

【讨论】:

  • 不错的一个。我不知道你可以在没有标签的情况下使用t 命令。
  • @SLePort:其实你需要一个标签,但是这个名字是空的。
  • 谢谢。这两个似乎都将所有连字符翻译成下划线,即使是在 ); 的第一个实例之后的那些。
  • @uint32:我回答了您问题的第一个版本,即没有多行示例的版本。因此,我的答案和其他答案旨在按行工作。现在你的问题完全不同了。
  • @Casimir et Hippolyte:感谢您的意见。很抱歉,我最初的问题并不像应有的那么清楚。
【解决方案2】:

(?:(?!PAT).)*PAT 就像 [^CHAR]CHAR,所以

s/\G (?: (?! \); | - ) . )* \K - /_/xsg

替代方案:

s/\G (?: (?! \); ) [^-] )* \K - /_/xg

最快:

s/\G (?: [^)-]++ | \)(?!;) )* \K - /_/xg

【讨论】:

    【解决方案3】:

    使用 GNU sed:

    sed -E ':a;s/^([^)]*)-([^)]*\);)/\1_\2/;ta;'
    

    【讨论】:

      【解决方案4】:

      我不会尝试使用神奇的正则表达式来解决它,而是:

      #!/usr/bin/env perl
      use strict;
      use warnings;
      
      while ( <DATA> ) {
         if ( m/CREATE TABLE/ .. /\);/ ) { 
            s/-/_/g;
         }
         print;
      }
      
      
      __DATA__
      CREATE TABLE e_00_90 (
      Last_Name nvarchar(50),
        Initials nvarchar(3),
        Company_Division nvarchar(50),
        Status nvarchar(12),
        Ckeyword5 nvarchar(15),
        Value_of_Contract_-_Overh decimal(20,2)
      );
      insert into export_00_90 values ('Sample-One', 'R', 'Div 1', 'Expired', 'ANONYTR', 5000);
      insert into export_00_90 values ('Sample Two', 'R', 'Div_2', 'Expired', 'WISHBONE', 13000);
      

      范围运算符可让您测试您是否在两个分隔符之间,并且仅在此处应用表达式。

      作为一个班轮,这将是:

      perl -pi -e 'm/CREATE TABLE/ .. /\);/ && s/-/_/g' 00-90.sql
      

      【讨论】:

        猜你喜欢
        • 2016-10-16
        • 1970-01-01
        • 1970-01-01
        • 2016-07-28
        • 2021-08-26
        • 1970-01-01
        • 2013-01-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多