我有一个“;”分隔文件:
aa;;;;aa
rgg;;;;fdg
aff;sfg;;;fasg
sfaf;sdfas;;;
ASFGF;;;;fasg
QFA;DSGS;;DSFAG;fagf
我想用\N
处理它来替换缺失的值。
结果应该是:
aa;\N;\N;\N;aa
rgg;\N;\N;\N;fdg
aff;sfg;\N;\N;fasg
sfaf;sdfas;\N;\N;\N
ASFGF;\N;\N;\N;fasg
QFA;DSGS;\N;DSFAG;fagf
我正在尝试使用sed脚本:
sed "s/;\(;\)/;\\N\1/g" file1.txt >file2.txt
但我得到的是
aa;\N;;\N;aa
rgg;\N;;\N;fdg
aff;sfg;\N;;fasg
sfaf;sdfas;\N;;
ASFGF;\N;;\N;fasg
QFA;DSGS;\N;DSFAG;fagf
答案 0 :(得分:5)
您不需要将第二个分号括在括号中,只是在替换字符串中将其用作\1
。您可以在替换字符串中使用;
:
sed 's/;;/;\\N;/g'
正如您所注意到的,当它找到一对分号时,它会用所需的字符串替换它,然后跳过它,而不是再次读取第二个分号,这使得它在每两个分号后插入\N
。
解决方案是使用积极的前瞻; regex
为/;(?=;)/
但sed
不支持。
但是可以使用sed
以简单的方式解决问题:复制搜索命令;第一个命令用;;
替换;\N
的奇怪外观,第二个命令用于处理偶数外观。最终结果是你需要的结果。
命令很简单:
sed 's/;;/;\\N;/g;s/;;/;\\N;/g'
它复制了上一个命令,并使用;
和g
之间的s
来分隔它们。或者,您可以为每个搜索表达式使用-e
命令行选项:
sed -e 's/;;/;\\N;/g' -e 's/;;/;\\N;/g'
<强>更新强>
OP在评论中提出&#34;如果我的文件有100列怎么办?&#34;
让我们试试看它是否有效:
$ echo "0;1;;2;;;3;;;;4;;;;;5;;;;;;6;;;;;;;" | sed 's/;;/;\\N;/g;s/;;/;\\N;/g'
0;1;\N;2;\N;\N;3;\N;\N;\N;4;\N;\N;\N;\N;5;\N;\N;\N;\N;\N;6;\N;\N;\N;\N;\N;\N;
看,妈!有用! : - )
更新#2
我忽略了这样一个事实,即问题并没有要求用其他内容替换;;
,而是替换使用;
分隔列的文件中的空/缺少值。因此,当表达式出现在行的开头或结尾时,我的表达式不会修复缺失值。
正如OP在评论中添加的那样,完整的sed
命令是:
sed 's/;;/;\\N;/g;s/;;/;\\N;/g;s/^;/\\N;/g;s/;$/;\\N/g'
或(为了便于阅读):
sed -e 's/;;/;\\N;/g;' -e 's/;;/;\\N;/g;' -e 's/^;/\\N;/g' -e 's/;$/;\\N/g'
另外两个步骤取代了&#39 ;;&#39;当他们在开始或结束时找到它时。
答案 1 :(得分:3)
您可以将此sed
命令与2 s
(替换)命令一起使用:
sed 's/;;/;\\N;/g; s/;;/;\\N;/g;' file
aa;\N;\N;\N;aa
rgg;\N;\N;\N;fdg
aff;sfg;\N;\N;fasg
sfaf;sdfas;\N;\N;
ASFGF;\N;\N;\N;fasg
QFA;DSGS;\N;DSFAG;fagf
或在perl
命令中使用 lookarounds regex :
perl -pe 's/(?<=;)(?=;)/\\N/g' file
aa;\N;\N;\N;aa
rgg;\N;\N;\N;fdg
aff;sfg;\N;\N;fasg
sfaf;sdfas;\N;\N;
ASFGF;\N;\N;\N;fasg
QFA;DSGS;\N;DSFAG;fagf
答案 2 :(得分:2)
主要问题是,对于一次替换,您不能多次使用相同的字符:
s/;;/..../g
:第二个;
无法重复用于;;;
如果你想使用sed而不使用类似Perl的正则表达式模式,你可以使用带有条件命令t
的循环:
sed ':a;s/;;/;\\N;/g;ta;' file
:a
定义了标签“a”,ta
只有在替换了某些内容时才会转到此标签。
对于行尾的;
(并处理最终的尾随空格):
sed ':a;s/;;/;\\N;/g;ta; s/;[ \t\r]*$/;\\N/1' file
答案 3 :(得分:1)
这个awk one-liner会给你你想要的东西:
awk -F';' -v OFS=';' '{for(i=1;i<=NF;i++)if($i=="")$i="\\N"}7' file
如果你真的想要这一行:sfaf;sdfas;\N;\N;\N
,这条线适合你:
awk -F';' -v OFS=';' '{for(i=1;i<=NF;i++)if($i=="")$i="\\N";sub(/;$/,";\\N")}7' file
答案 4 :(得分:1)
sed 's/;/;\\N/g;s/;\\N\([^;]\)/;\1/g;s/;[[:blank:]]*$/;\\N/' YourFile
概念:
;
;
的特殊情况,最后在行尾答案 5 :(得分:1)
这可能适合你(GNU sed):
sed -r ':;s/^(;)|(;);|(;)$/\2\3\\N\1\2/g;t' file
有4种情况可能会出现空字段:在记录的开头,2个字段分隔符之间,空字段后面的空字段和记录的结尾。可以采用轮换来满足上述情况1,2和4,并且可以通过使用循环(:;...;t
)的第二次传递来满足senario 3。使用g
标志可以在两次传递中替换多个senarios。