在由未知字符分隔同一行匹配并更换一个图案多次(match and replace one patte

2019-10-23 20:51发布

鉴于形式的输入:

select * from foo where ts>@(-2 days) and ts < @(-1 hour)

(这当然只是一个例子。我想支持的任何查询构建体和在@任何表达式())

我要替换的每个表达式@()与评价的结果date --date=exp +%s ,其中“EXP”是表达(因此在结果上面的例子将是

select * from foo where ts>1436694136 and ts < 1436863336

更一般地,如何更换从图案作为参数调用与捕获一个shell命令的结果的模式?

(我标记用Perl和bash的问题,但我开到任何东西)

Answer 1:

使用GNU sed的:

$ sql_expr="select * from foo where ts>@(-2 days) and ts < @(-1 hour)"

$ sed -r 's|@\(([^)]*)\)|$(date +%s --date "now\1")|g; s|.*|echo "&"|e' <<< "$sql_expr"

Gave:
select * from foo where ts>1436696209 and ts < 1436865409

请注意,此代码假定的内容@(...)是有效的表达式,日期计算。

说明:

  1. 首先表达将取代所有@()出现与$(date +%s --date "now _expression_")其中_expression_将是像-2 days
  2. 第二替换表达增加echo "..."周围的整个字符串和执行所产生的线。 您可以删除e标志在第二个表达式找出什么命令得到实际执行。


Answer 2:

类似下面(未经测试)

#!/usr/bin/perl
use strict;
use warnings;
my $date1;
my $date2;
my $expr = q{select * from foo where ts>@(-2 days) and ts < @(-1 hour)};
if( $expr =~ m#\@\((.*?)\) and .*? \@\((.*?)\)# ){
    $date1 = $1;
    $date2 = $2;
}
my $expr1 = `date --date=$date1 +%s`;
my $expr2 = `date --date=$date2 +%s`;

#now search and replace the $expr

$expr =~ s#\@\((.*?)\)#$expr1;
$expr =~ s#< \@\((.*?)\)#<.$expr2;

print "Final expression is $expr\n";


文章来源: match and replace one pattern multiple times in the same line delimited by unknown characters
标签: linux bash perl