我正在努力解决这个问题,我希望将一组行连接成一行/一行。我文件的每一行(titi / toto / tata)有2或3个以“;”分隔的字段所以我的输入是这样的:
titi1
titi2
titi3
43;75;97
1;2;87
toto1
toto2
toto3
40;50;60
tata1
tata2
tata3
4;5;2
5;3;7
2;5;9
我需要这个输出:
titi1;titi2;titi3;43;75;97
titi1;titi2;titi3;1;2;87
toto1;toto2;toto3;40;50;60
tata1;tata2;tata3;4;5;2
tata1;tata2;tata3;5;3;7
tata1;tata2;tata3;2;5;9
那么你可以看到前3行是信息(toto / tata等...),应该在数字开始后为每一行重复这些信息。
首先,我的输入只有一行数字,所以它是一个4乘4的分组。所以我在论坛搜索了我找到了一个例子并用这样的getline做了这个:
awk '{getline b; getline c; getline d;printf("%s %s %s %s\n",$0,b,c,d)}'
但后来我开始有2个甚至3个数字... ...所以我正在努力做一个“条件”,理解它应该重复前3个lign每次它看到一个从数字开始的lign。
该计划应如此:
awk 'f&&/^[^0-9]/{b="";f=0} /^[^0-9]/{b=b$0";"} /^[0-9]/{print b$0;f=1}'
说明:
1. /^[^0-9]/{b=b$0";"}
2. /^[0-9]/{print b$0;f=1}
3. f&&/^[^0-9]/{b="";f=0}
$0
,设置标志你可以尝试一下吗?
awk '
{
sub(/ +$/,"")
}
/^[a-zA-Z]+/{
if(val && flag){
val=""
}
val=val?val ";" $0:$0
flag=""
next
}
{
flag=1
print val ";" $0
}' Input_file
解决方案第二:如果您的Input_file可以将最后一行作为tot
等,并且您也想要打印它,那么请使用以下内容。
awk '
{
sub(/ +$/,"")
}
/^[a-zA-Z]+/{
if(val && flag){
val=""
}
val=val?val ";" $0:$0
flag=""
next
}
{
flag=1
print val ";" $0
}
END{
if(val && !flag){
print val
}
}' Input_file
$ awk -F';' 'NF>1{print s $0; p=1; next} p{s=p=""} {s=s $0 FS}' file
titi1;titi2;titi3;43;75;97
titi1;titi2;titi3;1;2;87
toto1;toto2;toto3;40;50;60
tata1;tata2;tata3;4;5;2
tata1;tata2;tata3;5;3;7
tata1;tata2;tata3;2;5;9
你的原始剧本 - 请参阅http://awk.freeshell.org/AllAboutGetline,了解为什么不使用getline(或大多数其他情况)以及如何在适当的情况下在极少数情况下正确调用getline。
你可以尝试这个awk:
awk -F';' 'NF==1{if(b){a=b=""};a=a$0FS;next}{b=1;$0=a$0}1' infile
而且更容易理解
awk -F ';' '
NF==1 {
if ( b ) {
a = b = ""
}
a = a $0 FS
next
}
{
b = 1
$0 = a $0
} 1
' infile
这可能适合你(GNU sed):
sed -r '/;/{:a;G;s/([^\n]*)\n(.*)/\2\n\1/;s/.//;s/\s*\n/;/g;n;/;/ba;x;z;x};H;d' file
使用保留空间存储每条记录的第一部分。遇到记录的结尾部分时,追加保留空间,重新排列最后一部分以跟随第一部分,删除第一个换行符并用分号替换剩余的换行符。打印记录,如果下一行是记录重复的结尾部分。否则,清除保留空间并将当前行附加到保留空间。