找到模式(YYYY-MM-DD)并将其替换为用撇号连接的相同值

时间:2019-01-28 18:50:54

标签: bash shell sed nsregularexpression

我有这种数据:

1,1990-01-01,2,A,2015-02-09 
1,NULL,2,A,2015-02-09
1,1990-01-01,2,A,NULL

并寻找解决方案,该解决方案将用旧值替换文件中的每个日期,但添加撇号。该示例的基本预期结果将是:

1,'1990-01-01',2,A,'2015-02-09' 
1,NULL,2,A,'2015-02-09'
1,'1990-01-01',2,A,NULL

我已经找到了一种方法来找到与我的日期相匹配的模式,但是仍然无法找到可以替换的模式。

sed 's/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/????/' a.txt > b.txt

6 个答案:

答案 0 :(得分:1)

通过用括号()括起来来将日期分组。然后,您可以将此捕获的组与\1一起使用(第二个组为\2等。)

sed "s/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)/'\1'/g"

请注意末尾的g,以确保替换所有匹配项(如果一行中有多个匹配项)。


如果将-r开关添加到sed,则可以省略()之前的笨拙的反斜杠:

sed -r "s/([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])/'\1'/g"

这可以使用量词进一步简化:

sed -r "s/([0-9]{4}-[0-9]{2}-[0-9]{2})/'\1'/g"

甚至:

sed -r "s/([0-9]{4}-([0-9]{2}){2})/'\1'/g"

如评论中所述:此外,在这种特殊情况下,可以使用&代替\1,它匹配整个查找表达式,并省略()

sed -r "s/[0-9]{4}(-[0-9]{2}){2}/'&'/g"

答案 1 :(得分:1)

您需要使用捕获组,并用g标志替换 all 个匹配项。

sed 's/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)/'"'"'\1'"'"'/g' a.txt > b.txt

替换文本有点令人困惑,因为shell中的单引号字符串不能包含单引号,因此您必须关闭单引号字符串,然后使用双引号单引号。在$'...'中使用bash样式的引号会稍微简化一点,但需要转义反斜杠。

sed $'s/\\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\\)/\'\1\'/g' a.txt > b.txt

或者,您可以直接对脚本加双引号,因为其中目前没有任何内容可以扩展:

sed "s/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)/'\1'/g" a.txt > b.txt

还有一种特殊的&替换文本,它可以扩展到正则表达式匹配的内容,因此可以避免使用显式捕获组:

sed "s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/'&'/g" a.txt > b.txt

答案 2 :(得分:0)

这是awk中的一个:

$ awk -v q="'" '
BEGIN { FS=OFS="," }                         # set selimiters
{
    for(i=1;i<=NF;i++)                       # loop all fields
        if($i~/[0-9]{4}-[0-9]{2}-[0-9]{2}/)  # if field has a date looking string
            $i=q $i q                        # quote it
}1' file

输出:

1,'1990-01-01',2,A,'2015-02-09'
1,NULL,2,A,'2015-02-09'
1,'1990-01-01',2,A,NULL

答案 3 :(得分:0)

请您尝试以下操作。(match中提到的REGEX也可以写为[0-9]{4}-[0-9]{2}-[0-9]{2},但是由于我的awk是旧版本,因此无法对其进行测试,因此您可以尝试一次)

awk -v s1="'" '
{
   while(match($0,/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/)){
      val=val substr($0,1,RSTART-1) s1 substr($0,RSTART,RLENGTH) s1
      $0=substr($0,RSTART+RLENGTH)
   }
   print val
   val=""
}'   Input_file

输出如下。

1,'1990-01-01',2,A,'2015-02-09'
1,NULL,2,A,'2015-02-09'
1,'1990-01-01'

答案 4 :(得分:0)

使用GNU sed:

sed -E 's/([0-9]{2,4}-?){3}/'\''&'\''/g' file

根据文件内容的不同,日期也可能描述为12,后跟九个破折号或数字的组合:

sed -E 's/[12][-0-9]{9}/'\''&'\''/g" file

答案 5 :(得分:0)

使用Perl,这很简单

perl -pe ' s/(\d{4}-\d\d-\d\d)/\x27$1\x27/g '

带输入-\ x27用于单引号

$ cat liubo.txt
1,1990-01-01,2,A,2015-02-09
1,NULL,2,A,2015-02-09
1,1990-01-01,2,A,NULL

$ perl -pe ' s/(\d{4}-\d\d-\d\d)/\x27$1\x27/g ' liubo.txt
1,'1990-01-01',2,A,'2015-02-09'
1,NULL,2,A,'2015-02-09'
1,'1990-01-01',2,A,NULL

$

如果要使用单引号,请转义$并将命令包装在双引号中

$ perl -pe " s/(\d{4}-\d\d-\d\d)/\'\$1\'/g " liubo.txt
1,'1990-01-01',2,A,'2015-02-09'
1,NULL,2,A,'2015-02-09'
1,'1990-01-01',2,A,NULL

$