sed 或 awk 替换前 14 个匹配项
Posted
技术标签:
【中文标题】sed 或 awk 替换前 14 个匹配项【英文标题】:sed or awk replace first 14 ocurrences 【发布时间】:2014-11-02 22:34:57 【问题描述】:我有一个由,
分隔的 csv 文件。不幸的是,最后一列是一个文本字段,一些字符串有逗号,所以当我尝试将 csv 导入 mysql 时,最后一列有时会被剪切。
我的 csv 文件示例(15 列) - 37k 行
Column1 ---------- Col2 Col3 Col4 ---- Col15
server.domain.tld,IP,Country,City,(...),text random text, text text
我需要用;
替换除最后一个,
之外的所有内容,因此当我使用;
作为列分隔符将文件导入MySQL 时,字段15 不会被剪切。另一种方法是将前 14 个 ',' 替换为 ';'。
我需要的输出:
Column1 ---------- Col2 Col3 Col4 ---- Col15
server.domain.tld;IP;Country;City;(...);text random text, text text
已经尝试过:
sed 's/,/;/g1-14'
sed 's/,/;/g1-14'
sed 's/,/;/g1,14'
sed 's/,/;/!14g'
sed 's/,/;/14g!'
sed 's/,/\1;\2;\3;\4;\5;\6;\7;\8;\9;\10;\11;\12;\13;\14;/'
【问题讨论】:
所以你不想替换最后一个逗号? 【参考方案1】:您可以将它们全部替换为另一个字符,然后从位置 15 重置:
sed -e 's/,/;/g' -e 's/;/,/15g' file
看一个例子:
$ cat a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$ sed -e 's/ /X/g' -e 's/X/ /15g' a
X1X2X3X4X5X6X7X8X9X10X11X12X13X14 15
想法基于Sed: Replace N first occurrences of a character。
【讨论】:
【参考方案2】:下面的 Perl 命令会将所有逗号替换为 ;
,除了最后一个。
perl -pe 's/,(?![^,]*$)/;/g' file
示例:
$ cat f
server.domain.tld,IP,Country,City,foo,bar,foo,bar,foobar,text random text, text text
$ perl -pe 's/,(?![^,]*$)/;/g' f
server.domain.tld;IP;Country;City;foo;bar;foo;bar;foobar;text random text, text text
【讨论】:
【参考方案3】:这是另一个想法:引用最后一个字段:
sed -r 's/(([^,]*,)14)(.*)/\1"\3"/' <<END
f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,a,b,c,d
one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen
a,b,c,d,e,f,g,h,i,j,k,l,m,n
less,than,fourteen
END
f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,"a,b,c,d"
one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,"fifteen"
a,b,c,d,e,f,g,h,i,j,k,l,m,n
less,than,fourteen
【讨论】:
我认为 awk 可能更适合这个awk -F, '$NF="\""$NF"\""' OFS=, file
我不同意,你必须先找到前 N 个字段,然后剩下的就是最后一个字段,即使它包含逗号
很公平,不应该是14
吗?【参考方案4】:
试试这个 sed 单线:
sed 's/,/;/g;s/;\([^;]*\)/,\1/'
一个小例子:
kent$ echo "foo,bar,foo,bar,foo,bar,here"|sed 's/,/;/g;s/;\([^;]*\)/,\1/'
foo;bar;foo;bar;foo;bar,here
我会添加一个带有s/.../.../ge
的gnu sed,虽然它比上面的行长一点
sed -r 's/(.*)(,.*)/echo $(echo \1|sed "s:,:;:g")\2/ge'
同样的例子:
kent$ echo "foo,bar,foo,bar,foo,bar,here"|sed -r 's/(.*)(,.*)/echo $(echo \1|sed "s:,:;:g")\2/ge'
foo;bar;foo;bar;foo;bar,here
【讨论】:
以上是关于sed 或 awk 替换前 14 个匹配项的主要内容,如果未能解决你的问题,请参考以下文章
sed / awk 匹配文件中第二次出现的正则表达式,并替换整行
Linux系列:grep过滤awk拆分sed替换的使用方法与区别