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

Find the pattern (YYYY-MM-DD) and replace it with the same value concatenating with apostrophes

我有这样的数据:

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

通过用括号 () 将模式括起来来捕捉一组中的日期。然后你可以将这个捕获的组与 </code> 一起使用(第二组将是 <code> 等)。

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

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


如果加上-r切换到sed,()前的笨拙的反斜杠就可以省略了:

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

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

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

甚至:

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

如评论中所述:此外,在这种特殊情况下,您可以使用 & 而不是 </code>,它匹配整个查找表达式,并省略 <code>():

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

这是 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

您需要使用捕获组,并将 所有 匹配项替换为 g 标志。

sed 's/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)/'"'"''"'"'/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]\)/\'\'/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

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

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

请你试试看。(match里面提到的REGEX也可以写成[0-9]{4}-[0-9]{2}-[0-9]{2}但是因为我的awk是旧版本所以无法测试,你可以试一次)

awk -v s1="'" '
{
   while(match([=10=],/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/)){
      val=val substr([=10=],1,RSTART-1) s1 substr([=10=],RSTART,RLENGTH) s1
      [=10=]=substr([=10=],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'

使用 GNU sed:

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

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

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

使用 Perl,很简单

perl -pe ' s/(\d{4}-\d\d-\d\d)/\x27\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\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

$