sed:如何替换多行模式中的所有内容?

时间:2015-04-16 10:38:37

标签: linux bash sed

我必须从另一个创建一个sql脚本来改变他们的内容。例如

SELECT value INTO val FROM table WHERE condition;
SELECT value2 INTO val2 FROM table WHERE condition1
                                   OR condition2;

所以我试过了

sed 's/FROM .*;/;/g'

但是它会返回

SELECT value INTO val ;
SELECT value2 INTO val2 FROM table WHERE condition1
                                   OR condition2;

而不是这个,这就是我需要的

SELECT value INTO val ;
SELECT value2 INTO val2 ;

有什么想法吗?基本上我想要做的就是删除'FROM'和下一个';'中包含的所有内容。

4 个答案:

答案 0 :(得分:2)

我认为您可以删除脚本中的'\ n',然后使用sed删除。

例如

cat test.sql |tr -d '\n'|sed 's/FROM [^;]*;/;\n/g'

答案 1 :(得分:2)

sed ':load
# load any multiline sequence before going further
/;[[:space:]]*$/ !{ N;b load
   }

# from here you have a full (multi)line to treat
s/[[:space:]]\{1,\}FROM[[:space:]].*;/ ;/
   ' YourFile

您需要先删除多行序列,然后再删除结尾(在加载部分循环,直到找到结束的;

  • :load:' goto'的地址标签稍后使用
  • /;[[:space:]]*$/:当行上没有结尾;时(最后会有一些结束空格)
    • N:在工作缓冲区中加载新行
    • b load:转到标签load(转到)
  • s/[[:space:]]\{1,\}FROM[[:space:]].*;/ ;/使用新格式更改整个当前工作缓冲区(所以单行和多行,但都以;结尾)。在这种情况下,Sed处理缓冲区而不是行,在这种情况下,新行与其他字符一样。

最后一行必须由;结束才能被处理,否则,最后一个(未完成的)序列将丢失

答案 2 :(得分:1)

awk是基于记录的,不像sed那样基于行,所以处理多行字符串没有问题:

$ awk 'BEGIN{RS=ORS=";"}{gsub(/FROM .*/,"")}1' file
SELECT value INTO val ;
SELECT value2 INTO val2 ;

以上只是将记录分隔符设置为;而不是默认换行符,并对结果字符串进行操作,该字符串可以包含换行符,就像任何其他字符一样。

答案 3 :(得分:0)

据我所知,你要么必须摆脱换行符分隔符

tr -d '\n'

或在re.compile中使用 Pythons “re.M | re.DOTALL”参数

例如(粗略地说):

pattern = re.compile('FROM[^;]*;', re.M | re.DOTALL)
result = re.findall(pattern, file)

通常,当我需要regex over newlines时,我总是最终得到Python。 Bash过于基于新行,因此很难弯曲它。 但是,如果你真的需要使用bash,那么用占位符替换'\ n'就足够了。