sed:如何替换多行模式中的所有内容?
sed: How to replace all content in a multi-line pattern?
我必须从另一个更改其内容的脚本创建一个 sql 脚本。例如
SELECT value INTO val FROM table WHERE condition;
SELECT value2 INTO val2 FROM table WHERE condition1
OR condition2;
所以我试过了
sed 's/FROM .*;/;/g'
但这是returns这个
SELECT value INTO val ;
SELECT value2 INTO val2 FROM table WHERE condition1
OR condition2;
而不是这个,这是我需要的
SELECT value INTO val ;
SELECT value2 INTO val2 ;
有什么想法吗?基本上我想做的是删除 'FROM' 和下一个 ';' 中包含的所有内容
我认为您可以删除脚本中的“\n”,然后使用 sed 删除 from。
例如
cat test.sql |tr -d '\n'|sed 's/FROM [^;]*;/;\n/g'
据我所知,你要么必须去掉换行符
tr -d '\n'
或在re.compile
中使用Pythons"re.M | re.DOTALL"参数
例如(粗略地说):
pattern = re.compile('FROM[^;]*;', re.M | re.DOTALL)
result = re.findall(pattern, file)
通常,当我需要对换行符进行正则表达式时,我总是以 Python 结束。 Bash 太基于换行符,很难弯曲它来做到这一点。
但是,如果您确实需要使用 bash.
,则用占位符替换 '\n' 可能就足够了
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:]]*$/
:当没有结尾;
就行了(最终有些结尾space以后
N
: 在工作缓冲区中加载一个新行
b load
: 转到标签 load
(转到)
s/[[:space:]]\{1,\}FROM[[:space:]].*;/ ;/
用您的新格式更改整个当前工作缓冲区(单行和多行,但都以 ;
结尾)。 Sed 在这种情况下处理缓冲区而不是一行,新行在这种情况下与其他字符一样。
最后一行需要以;
结尾才能处理,否则,最后(不完整的)序列将丢失
awk是基于记录的,不像sed那样是基于行的,所以处理多行字符串没有问题:
$ awk 'BEGIN{RS=ORS=";"}{gsub(/FROM .*/,"")}1' file
SELECT value INTO val ;
SELECT value2 INTO val2 ;
上面只是将记录分隔符设置为 ;
而不是默认的换行符,并对结果字符串进行操作,它可以像任何其他字符一样包含换行符。
我必须从另一个更改其内容的脚本创建一个 sql 脚本。例如
SELECT value INTO val FROM table WHERE condition;
SELECT value2 INTO val2 FROM table WHERE condition1
OR condition2;
所以我试过了
sed 's/FROM .*;/;/g'
但这是returns这个
SELECT value INTO val ;
SELECT value2 INTO val2 FROM table WHERE condition1
OR condition2;
而不是这个,这是我需要的
SELECT value INTO val ;
SELECT value2 INTO val2 ;
有什么想法吗?基本上我想做的是删除 'FROM' 和下一个 ';' 中包含的所有内容
我认为您可以删除脚本中的“\n”,然后使用 sed 删除 from。
例如
cat test.sql |tr -d '\n'|sed 's/FROM [^;]*;/;\n/g'
据我所知,你要么必须去掉换行符
tr -d '\n'
或在re.compile
中使用Pythons"re.M | re.DOTALL"参数例如(粗略地说):
pattern = re.compile('FROM[^;]*;', re.M | re.DOTALL)
result = re.findall(pattern, file)
通常,当我需要对换行符进行正则表达式时,我总是以 Python 结束。 Bash 太基于换行符,很难弯曲它来做到这一点。 但是,如果您确实需要使用 bash.
,则用占位符替换 '\n' 可能就足够了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:]]*$/
:当没有结尾;
就行了(最终有些结尾space以后N
: 在工作缓冲区中加载一个新行b load
: 转到标签load
(转到)
s/[[:space:]]\{1,\}FROM[[:space:]].*;/ ;/
用您的新格式更改整个当前工作缓冲区(单行和多行,但都以;
结尾)。 Sed 在这种情况下处理缓冲区而不是一行,新行在这种情况下与其他字符一样。
最后一行需要以;
结尾才能处理,否则,最后(不完整的)序列将丢失
awk是基于记录的,不像sed那样是基于行的,所以处理多行字符串没有问题:
$ awk 'BEGIN{RS=ORS=";"}{gsub(/FROM .*/,"")}1' file
SELECT value INTO val ;
SELECT value2 INTO val2 ;
上面只是将记录分隔符设置为 ;
而不是默认的换行符,并对结果字符串进行操作,它可以像任何其他字符一样包含换行符。