我的文本文件中包含几行以" i"一些与" u>我"和其他作为"?"这些行下方总共有2行,我想加入这两行(追加),其中包含任意位置的行""。
尝试了awk,sed但没有获得可以解决此问题的确切字符串。
档案数据: -
*i 80.95.226.72/29 n/a None
193.105.101.26 None -
28834 64690
*? 85.118.193.0/25 n/a None
193.105.101.26 None -
28834 64814
u*>i 213.226.55.0/24 n/a None
193.105.101.27 None -
28834 64757
*i 80.65.79.160/27 n/a None
193.105.101.26 None -
28834 9146
预期产出: -
*i,80.95.226.72/29,n/a,None,193.105.101.26 ,None,-,28834,64690
*?,85.118.193.0/25,n/a,None,193.105.101.26 ,None,-,28834,64814
u*>i,213.226.55.0/24,n/a,None193.105.101.27 ,None,-,28834,9146
答案 0 :(得分:0)
awk 解决方案,无论任何行中的字段数量是多少,都是:
$ cat tst.awk
BEGIN{OFS=","}
NF && p && !/\*/ { p = p OFS coalesce(); next}
/\*/{ if (p) print p; p=coalesce()}0
function coalesce(){
s=""
for (i=1;i<=NF;i++) s=s (i==NF ? $i : $i OFS)
return s
}
<强>解释强>:
BEGIN{OFS=","} # set Output Field Separator to ","
NF && p && !/\*/ { # if nr of fields > 0, not containing
# '*' and p is set
p = p OFS coalesce(); next # add formatted $0 to p
}
/\*/{ # if $0 contains '*'
if (p) print p; # if p then print it
p=coalesce() # initialize p
}0 # ignore rest of lines
function coalesce(){
s=""
for (i=1;i<=NF;i++) s=s (i==NF ? $i : $i OFS)
return s
}
<强>测试强>:
$ awk -f tst.awk input.txt
*i,80.95.226.72/29,n/a,None,193.105.101.26,None,-,28834,64690
*?,85.118.193.0/25,n/a,None,193.105.101.26,None,-,28834,64814
u*>i,213.226.55.0/24,n/a,None,193.105.101.27,None,-,28834,64757
或 oneliner :
$ awk -v OFS=, '$0 && p && !/\*/ { p = p OFS coalesce(); next}/\*/{ if (p) print p; p=coalesce()}0;function coalesce(){s="";for (i=1;i<=NF;i++) s=s (i==NF ? $i : $i OFS);return s}' input.txt
答案 1 :(得分:0)
单行 awk
$ awk -v OFS=, 'NF{$1=$1; s=(s?s OFS:"") $0}NF==2 && s{print s; s=""}' infile
要解决您的帖子标题:
awk -v OFS=, -v n=2 'NF{$1=$1}/\*/{s=$0;next}s && NF && n>=c++{s = s OFS $0}c==n{print s; s=c=""}' infile
更好的可读性:
awk -v OFS=, -v n=2 '
NF{
$1 = $1
}
/\*/{
s=$0
next
}
s && NF && n>=c++{
s = s OFS $0
}
c==n{
print s
s = c = ""
}
' infile
<强>解释强>
NF{ $1 = $1 }
如果行/记录/行至少有一个字段(
NF
没有字段。) 记录),然后重新编译记录,因为当你$1=$1
(或任何 对字段的其他分配)它导致记录重新编译$0
每FS
替换为OFS
重建。
/\*/{ s = $0; next }
如果行包含
*
,则为变量s
分配当前值 记录/行/行,然后转到下一行。
s && NF && n>=c++{ s = s OFS $0 }
如果设置了变量
s
,则记录至少包含1个字段和变量n
大于或等于变量c++
(++
增量 运算符),然后连接变量s
c==n{print s; s=c=""}
如果变量
c
等于变量n
,则打印变量s
,然后 取消变量s
和c
<强>输入:强>
$ cat infile
*i 80.95.226.72/29 n/a None
193.105.101.26 None -
28834 64690
*? 85.118.193.0/25 n/a None
193.105.101.26 None -
28834 64814
u*>i 213.226.55.0/24 n/a None
193.105.101.27 None -
28834 64757
<强>输出-1:强>
$ awk -v OFS=, 'NF{$1=$1; s=(s?s OFS:"") $0}NF==2 && s{print s; s=""}' infile
*i,80.95.226.72/29,n/a,None,193.105.101.26,None,-,28834,64690
*?,85.118.193.0/25,n/a,None,193.105.101.26,None,-,28834,64814
u*>i,213.226.55.0/24,n/a,None,193.105.101.27,None,-,28834,64757
<强>输出-2:强>
$ awk -v OFS=, -v n=2 'NF{$1=$1}/\*/{s=$0;next}s && NF && n>=c++{s = s OFS $0}c==n{print s; s=c=""}' infile
*i,80.95.226.72/29,n/a,None,193.105.101.26,None,-,28834,64690
*?,85.118.193.0/25,n/a,None,193.105.101.26,None,-,28834,64814
u*>i,213.226.55.0/24,n/a,None,193.105.101.27,None,-,28834,64757
答案 2 :(得分:0)
你能不能尝试跟随awk。
awk 'NF{gsub(/ +/,",");printf("%s",!/^,/?(NR!=1?RS $0:$0):$0)} END{print ""}' Input_file
输出如下。
*i,80.95.226.72/29,n/a,None,193.105.101.26,None,-,28834,64690
*?,85.118.193.0/25,n/a,None,193.105.101.26,None,-,28834,64814
u*>i,213.226.55.0/24,n/a,None,193.105.101.27,None,-,28834,64757
现在也添加解释和非单线形式的解决方案。
awk '
NF{ ##If a line is NON-empty then do following steps.
gsub(/ +/,","); ##Globally substituting all continuous spaces with a single comma in each non-empty line.
printf("%s",!/^,/?(NR!=1?RS $0:$0):$0) ##printing line here with a condition if line number is NOT equal to 1 and starts with comma then print RS(whose default value is a new line and current line) else print current line, outer else print current line.
}
END{
print "" ##Printing NULL value here to print a new line.
}
' Input_file ##Mentioning Input_file name here too.