我正在寻找一种解析多行命令输出的方法;将nth
行的每个倍数分组并格式化为CSV格式。
$ cat file
ABC
123
62p4-123
DEF
456
62p4-456
我需要在每个3rd
行分组的o / p,以及3的倍数,即第3,第6和第9,然后分别以逗号分隔格式分别为第1,第4和第7以及第2,第5和第8 < / p>
ABC,DEF
123,456
62p4-123,62p4-456
这只是一个示例格式,我的实际用例是json
o / p,我想使用bash
中的工具/实用程序进行格式设置,而且我不需要格式化选项在jq
范围内,我用于解析数据。
我在awk
awk 'NR % 3 == 0'
中找到了几种方式,但我不能对其他行重复这些方法。
编辑: - 我在这里更新从jq
返回的实际JSON o / p以获得最有效的解决方案
4496
http://xxx/yyy
/home/build/branches/mmm/file1
4497
http://xxx/yyy/zzz
/home/build/branches/mmm/file1
4498
http://xxx/yyy/zzz
/home/build/branches/mmm/otherfile.c
预期o / p
4496,4497,4498
http://xxx/yyy,http://xxx/yyy/zzz,http://xxx/yyy/zzz
/home/build/branches/mmm/file1,/home/build/branches/mmm/file1,home/build/branches/mmm/otherfile.c
答案 0 :(得分:4)
这是一种更简单的方法
$ pr -2ts, file
ABC,DEF
123,456
62p4-123,62p4-456
对于另一个输入,将列数更改为3。
$ pr -3ts, file
4496,4497,4498
http://xxx/yyy,http://xxx/yyy/zzz,http://xxx/yyy/zzz
/home/build/branches/mmm/file1,/home/build/branches/mmm/file1,/home/build/branches/mmm/otherfile.c
如果您只知道行数,而不是最终列数,则可以执行此操作
$ pr -$(awk 'END{print NR/3}' file) -ts, file
答案 1 :(得分:2)
你可以使用这个awk:
awk -v OFS=, 'NR<4{a[NR]=$0; next} {i=(NR%3?NR%3:3); a[i] = a[i] OFS $0}
END{for(i=1; i<=3; i++) print a[i]}' file
4496,4497,4498
http://xxx/yyy,http://xxx/yyy/zzz,http://xxx/yyy/zzz
/home/build/branches/mmm/file1,/home/build/branches/mmm/file1,/home/build/branches/mmm/otherfile.c
答案 2 :(得分:1)
$ cat ip.txt
4496
http://xxx/yyy
/home/build/branches/mmm/file1
4497
http://xxx/yyy/zzz
/home/build/branches/mmm/file1
4498
http://xxx/yyy/zzz
/home/build/branches/mmm/otherfile.c
$ perl -lne '$i = ($.-1)%3; $f[$i] .= $f[$i] ? ",$_" : $_; END{print foreach (@f)}' ip.txt
4496,4497,4498
http://xxx/yyy,http://xxx/yyy/zzz,http://xxx/yyy/zzz
/home/build/branches/mmm/file1,/home/build/branches/mmm/file1,/home/build/branches/mmm/otherfile.c
这是一种替代解决方案,但在性能方面效率低下
$ (sed -n '1~3p' ip.txt ; sed -n '2~3p' ip.txt ; sed -n '3~3p' ip.txt) | pr -ats, -$(echo $(wc -l < ip.txt)/3 | bc)
4496,4497,4498
http://xxx/yyy,http://xxx/yyy/zzz,http://xxx/yyy/zzz
/home/build/branches/mmm/file1,/home/build/branches/mmm/file1,/home/build/branches/mmm/otherfile.c
答案 3 :(得分:1)
行人,纯Bash(≥4)方法,用mapfile
读取内存中的整个文件。
#!/bin/bash
n=3
mapfile -t ary < file
for ((i=0;i<n;++i)); do
for ((j=i;j<${#ary[@]};j+=n)); do
(( j >= n )) && printf ,
printf '%s' "${ary[j]}"
done
echo
done
这不是非常有效(所以不要将它用于非常大的文件)。
一种变体是在读取文件时建立要输出的行。
#!/bin/bash
n=3
ary=()
linenb=0
while IFS= read -r line; do
((linenb>=n)) && ary[linenb%n]+=,
ary[linenb++%n]+=$line
done < file
printf '%s\n' "${ary[@]}"
同样,这对于非常大的文件来说效率不高(但它是纯粹的Bash!)。
答案 4 :(得分:1)
$ awk '{k=((NR-1)%3)+1} {a[k]=(k in a ? a[k] "," : "") $0} END{for (i=1;i<=3;i++) print a[i]}' file
ABC,DEF
123,456
62p4-123,62p4-456
$ awk '{k=((NR-1)%3)+1} {a[k]=(k in a ? a[k] "," : "") $0} END{for (i=1;i<=3;i++) print a[i]}' file
4496,4497,4498
http://xxx/yyy,http://xxx/yyy/zzz,http://xxx/yyy/zzz
/home/build/branches/mmm/file1,/home/build/branches/mmm/file1,/home/build/branches/mmm/otherfile.c