使用sed处理带分隔符的文本文件

dax*_*x90 2 regex sed

我有一个 ";" 分隔文件:

aa;;;;aa
rgg;;;;fdg
aff;sfg;;;fasg
sfaf;sdfas;;;           
ASFGF;;;;fasg
QFA;DSGS;;DSFAG;fagf
Run Code Online (Sandbox Code Playgroud)

我想用一个替换缺失的值来处理它\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
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用sed脚本:

sed "s/;\(;\)/;\\N\1/g" file1.txt  >file2.txt
Run Code Online (Sandbox Code Playgroud)

但我得到的是

aa;\N;;\N;aa
rgg;\N;;\N;fdg
aff;sfg;\N;;fasg
sfaf;sdfas;\N;;         
ASFGF;\N;;\N;fasg
QFA;DSGS;\N;DSFAG;fagf
Run Code Online (Sandbox Code Playgroud)

axi*_*iac 5

您不需要将第二个分号括在括号中,只是为了\1在替换字符串中使用它.您可以;在替换字符串中使用:

sed 's/;;/;\\N;/g'
Run Code Online (Sandbox Code Playgroud)

正如您所注意到的,当它找到一对分号时,它会用所需的字符串替换它,然后跳过它,而不是再次读取第二个分号,这使得它\N在每两个分号后插入.

一个解决方案是使用积极的前瞻; 的regex/;(?=;)/,但sed不支持他们.

但是可以通过sed简单的方式解决问题:复制搜索命令; 第一个命令替换了;;with 的奇怪外观;\N,第二个命令处理偶数外观.最终的结果是你需要的.

命令很简单:

sed 's/;;/;\\N;/g;s/;;/;\\N;/g'
Run Code Online (Sandbox Code Playgroud)

它只是重复以前的命令,并使用;之间g,并s以separe他们.或者,您可以-e对每个搜索表达式使用命令行选项一次:

sed -e 's/;;/;\\N;/g' -e 's/;;/;\\N;/g'
Run Code Online (Sandbox Code Playgroud)

更新:

OP在评论中询问"如果我的文件有100列怎么办?"

让我们试试看它是否有效:

$ 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;
Run Code Online (Sandbox Code Playgroud)

看,妈!有用!:-)


更新#2

我忽略了这样一个事实,即问题不是要求;;用其他东西替换,而是替换;用于分隔列的文件中的空/缺失值.因此,当表达式出现在行的开头或结尾时,我的表达式不会修复缺失值.

正如OP在评论中添加的那样,完整的sed命令是:

sed 's/;;/;\\N;/g;s/;;/;\\N;/g;s/^;/\\N;/g;s/;$/;\\N/g'
Run Code Online (Sandbox Code Playgroud)

或(为了便于阅读):

sed -e 's/;;/;\\N;/g;' -e 's/;;/;\\N;/g;' -e 's/^;/\\N;/g' -e 's/;$/;\\N/g'
Run Code Online (Sandbox Code Playgroud)

另外两个步骤取代';' 当他们在开始或结束时找到它.