[英]process a delimited text file with sed
我有一個 ”;” 分隔文件:
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
您不需要將第二個分號括在括號中,只是在替換字符串中將其用作\\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在評論中詢問“如果我的文件有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;
看,媽! 有用! :-)
更新#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'
另外兩個步驟取代';' 當他們在開始或結束時找到它。
您可以將此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
主要問題是,對於單個替換,您不能使用多次相同的字符:
s/;;/..../g
:第二個;
不能在字符串中的下一個匹配中重復使用;;;
如果你想使用sed而不使用類似Perl的正則表達式模式,你可以使用帶有條件命令t
的循環:
sed ':a;s/;;/;\\N;/g;ta;' file
:a
定義了一個標簽“一”, ta
去只有當事情已被替換這個標簽。
對於;
在行尾(並處理最終的尾隨空格):
sed ':a;s/;;/;\\N;/g;ta; s/;[ \t\r]*$/;\\N/1' file
這個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
sed 's/;/;\\N/g;s/;\\N\([^;]\)/;\1/g;s/;[[:blank:]]*$/;\\N/' YourFile
概念:
;
;
在行尾之前最終有空間 這可能適合你(GNU sed):
sed -r ':;s/^(;)|(;);|(;)$/\2\3\\N\1\2/g;t' file
有4個可能出現空字段的情況:在記錄的開頭,2個字段分隔符之間,空字段后面的空字段和記錄的結尾。 可以采用輪換來滿足上述情況1,2和4,並且可以使用循環( :;...;t
)通過第二次傳遞來滿足senario 3。 使用g
標志可以在兩次傳遞中替換多個senarios。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.