找到模式 (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
根据您的文件内容,日期也可以描述为 1
或 2
后跟九个破折号或数字的组合:
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
$
我有这样的数据:
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
根据您的文件内容,日期也可以描述为 1
或 2
后跟九个破折号或数字的组合:
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
$