我一直在寻求用sed,awk或cut做这件事。我愿意使用任何其他命令行程序来管理数据。
我有一大堆以逗号分隔的数据。行有14到20列。我需要递归地连接第10列和每行第11列,这样每行只有14列。换句话说,这个:
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
将成为:
a,b,c,d,e,f,g,h,i,jkl,m,n,o,p
我可以获得前10列。我可以得到最后的N列。我可以连接列。我无法想到如何在一行中完成它,所以我可以通过它传递无穷无尽的数据流,最终每行只有14列。
示例(按要求):
行中有多少列?
sed 's/[^,]//g' | wc -c
获取前10列:
cut -d, -f1-10
获取最后4列:
rev | cut -d, -f1-4 | rev
连接第10列和第11列,之后显示第1-10列:
awk -F',' ' NF { print $1","$2","$3","$4","$5","$6","$7","$8","$9","$10$11}'
答案 0 :(得分:3)
var characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 ";
解决方案:
Awk
输出:
awk 'BEGIN{ FS=OFS="," }
{
diff = NF - 14;
for (i=1; i <= NF; i++)
printf "%s%s", $i, (diff > 1 && i >= 10 && i < (10+diff)?
"": (i == NF? ORS : ","))
}' file
答案 1 :(得分:2)
如果perl
没问题,可以像awk
一样用于流处理
$ cat ip.txt
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
1,2,3,4,5,6,3,4,2,4,3,4,3,2,5,2,3,4
1,2,3,4,5,6,3,4,2,4,a,s,f,e,3,4,3,2,5,2,3,4
$ awk -F, '{print NF}' ip.txt
16
18
22
$ perl -F, -lane '$n = $#F - 4;
print join ",", (@F[0..8], join("", @F[9..$n]), @F[$n+1..$#F])
' ip.txt
a,b,c,d,e,f,g,h,i,jkl,m,n,o,p
1,2,3,4,5,6,3,4,2,43432,5,2,3,4
1,2,3,4,5,6,3,4,2,4asfe3432,5,2,3,4
-F, -lane
拆分保存在,
数组@F
个结果
$n = $#F - 4
幻数,确保输出结束14列。 $#F
给出数组的最后一个元素的索引(如果输入行少于14列,则不会工作)join
有助于将数组元素与指定的字符串@F[0..8]
带有前9个元素的数组切片@F[9..$n]
和@F[$n+1..$#F]
其他切片
借鉴Ed Morton's regex based solution
$ perl -F, -lape '$n=$#F-13; s/^([^,]*,){9}\K([^,]*,){$n}/$&=~tr|,||dr/e' ip.txt
a,b,c,d,e,f,g,h,i,jkl,m,n,o,p
1,2,3,4,5,6,3,4,2,43432,5,2,3,4
1,2,3,4,5,6,3,4,2,4asfe3432,5,2,3,4
$n=$#F-13
幻数^([^,]*,){9}\K
前9个字段([^,]*,){$n}
要更改的字段$&=~tr|,||dr
使用tr
删除逗号e
此修饰符允许在替换部分答案 2 :(得分:2)
使用GNU awk为第3个arg匹配()和gensub():
$ cat tst.awk
BEGIN{ FS="," }
match($0,"(([^,]+,){9})(([^,]+,){"NF-14"})(.*)",a) {
$0 = a[1] gensub(/,/,"","g",a[3]) a[5]
}
{ print }
$ awk -f tst.awk file
a,b,c,d,e,f,g,h,i,jkl,m,n,o,p
答案 3 :(得分:1)
你可以试试这个gnu sed
sed -E '
s/,/\n/9g
:A
s/([^\n]*\n)(.*)(\n)(([^\n]*\n){4})/\1\2\4/
tA
s/\n/,/g
' infile
答案 4 :(得分:1)
awk -F, '
{
for(i = 1; i <= NF; i++) {
OFS = (i > 9 && i < NF - 4) ? "" : ","
if(i == NF) OFS = "\n"
printf "%s%s", $i, OFS
}
}' input.txt
sed -r 's/,/#/10g; :l; s/#(.*)((#[^#]){4})/\1\2/; tl; s/#/,/g' input.txt
或者,更直接(没有循环),可能更快。
sed -r 's/,(.),(.),(.),(.)$/#\1#\2#\3#\4/; s/,//10g; s/#/,/g' input.txt
<强>输入强>
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u
<强>输出强>
a,b,c,d,e,f,g,h,i,jkl,m,n,o,p
a,b,c,d,e,f,g,h,i,jklmn,o,p,q,r
a,b,c,d,e,f,g,h,i,jklmnopq,r,s,t,u
答案 5 :(得分:0)
使用csvtool解决了类似的问题。源文件,是从其他答案之一复制的:
$ cat input.txt
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
1,2,3,4,5,6,3,4,2,4,3,4,3,2,5,2,3,4
1,2,3,4,5,6,3,4,2,4,a,s,f,e,3,4,3,2,5,2,3,4
串联列:
$ cat input.txt | csvtool format '%1,%2,%3,%4,%5,%6,%7,%8,%9,%10%11%12,%13,%14,%15,%16,%17,%18,%19,%20,%21,%22\n' -
a,b,c,d,e,f,g,h,i,jkl,m,n,o,p,,,,,,
1,2,3,4,5,6,3,4,2,434,3,2,5,2,3,4,,,,
1,2,3,4,5,6,3,4,2,4as,f,e,3,4,3,2,5,2,3,4
anatoly@anatoly-workstation:cbs$ cat input.txt