我有以下文字:
Name= Garen
Class= 9C
School= US
Name= Lulu
Class= 4A
Name= Kata
Class= 10D
School= UK
我得到了下面的 awk cmd:
awk '$Name ~/Name/ {printf $0;} $Class ~/Class/ {printf $0;} $School ~/School/ {print $0;} ' file.txt
但它以新行输出。像这样:
Name= Garen Class= 9C School= US
Name= Lulu Class= 4A Name= Kata Class= 10D School= UK
我希望它像这样输出:
Name= Garen ,Class= 9C ,School= US
Name= Lulu , Class= 4A ,
Name= Kata ,Class= 10D ,School= UK
如果遇到以下情况:
Name= Garen
Class= 9C
Last Name= Wilson
School= US
Name= Lulu
Class= 4A
Last Name= Miller
Name= Kata
Class= 10D
School= UK
Last Name= Thomas
并打印:
Name= Garen,Class= 9C,School= US
Name= Lulu,Class= 4A
Name= Kata,Class= 10D,School= UK
答案1
$ awk -v OFS=',' '/^Name/ { if (line != "") print line; line = $0; next } { line = line OFS $0 } END { if (line != "") print line }' file
Name= Garen,Class= 9C,School= US
Name= Lulu,Class= 4A
Name= Kata,Class= 10D,School= UK
随着问题中更新的输入,这会产生
Name= Garen,Class= 9C,Last Name= Wilson ,School= US,
Name= Lulu,Class= 4A,Last Name= Miller,
Name= Kata,Class= 10D,School= UK,Last Name= Thomas
如果要删除该Last Name
位,请在代码中显式忽略它awk
:
$ awk -v OFS=',' '/^Last Name/ { next } /^Name/ { if (line != "") print line; line = $0; next } { line = line OFS $0 } END { if (line != "") print line }' file
Name= Garen,Class= 9C,School= US,
Name= Lulu,Class= 4A,
Name= Kata,Class= 10D,School= UK
该awk
代码作为awk
带有注释的独立程序:
BEGIN {
# Set output field separator to a comma.
# This can also be done with -v OFS="," on the command line.
OFS = ","
}
/^Last Name/ {
# Ignore these lines
next
}
/^Name/ {
# A line starts with "Name".
# Print the accumulated line and reset the line variable.
# Continue immediately with next line of input.
if (line != "")
print line
line = $0
next
}
{
# Accumulate lines in the line variable.
# Delimit each input data with OFS (a comma).
line = line OFS $0
}
END {
# Print the last accumulated line.
if (line != "")
print line
}
(sed
这是一个几乎相同的解决方案来自另一个问题的答案)
/^Last Name/ d; # ignore these lines
/^Name/ b print_previous; # print previous record
H; # append this line to hold space
$ b print_previous; # print previous (last) record
d; # end processing this line
:print_previous; # prints a record accumulated in the hold space
x; # swap in the hold space
/^$/ d; # if line is empty, delete it
s/\n/,/g; # replace embedded newlines by commas
# (implicit print)
运行它:
$ sed -f script.sed file
Name= Garen,Class= 9C,School= US
Name= Lulu,Class= 4A
Name= Kata,Class= 10D,School= UK
答案2
您可以使用awk
以下单行代码来实现此目的,如下所示:
awk -F\< '/Name=/ {LGT=length($2);printf("\n%s,",substr($2,6,LGT))};
/Class=/ {LGT=length($2);printf(" %s,",substr($2,6,LGT))};
/School=/ {LGT=length($2);printf(" %s",substr($2,6,LGT))};
END {printf("\n") }' file.txt
该解决方案将按照记录(即原始file.txt
文件中的行)在 中出现的顺序打印它们file.txt
。我添加它是因为它是一个(简单)示例,说明如何使用awk
.
如之前的答案所示,file.txt 包含:
<text>Name= Garen</text>
<text>Class= 9C</text>
<text>School= US</text>
<text>Name= Lulu</text>
<text>Class= 4A</text>
<text>Name= Kata</text>
<text>Class= 10D</text>
<text>School= UK</text>
输出是:
Name= Garen, Class= 9C, School= US
Name= Lulu, Class= 4A
Name= Kata, Class= 10D, School= UK
答案3
awk '$Name ~/Name/ {printf $0;} $Class ~/Class/ {printf $0;} $School ~/School/ {print $0;} ' file.txt
所有$Name
,$Class
和 的$School
行为与 , 完全相同$0
,因为Name
,Class
和School
变量未定义,并且在awk
任何未定义的变量中具有 and 的数值0
(至少对于mawk
and gawk
),$
运算符将简单地将其参数转换为数字。其他awk
实现可能会因错误而退出(标准未指定该行为)。
试试这个:
awk -F ' *= *' '$1~/^(Name|Class|School)$/{
if($1 in a){ for(i in a) delete a[i]; comma = ""; printf ORS }
printf "%s%s= %s", comma, $1, $2; a[$1] = comma = ", "
}
END{if(comma) printf ORS}
' file.txt
Name= Garen, Class= 9C, School= US
Name= Lulu, Class= 4A
Name= Kata, Class= 10D, School= UK
上面的示例尝试对键/值元组进行分组,无论它们的顺序如何,并且是通用的(它会起作用)相同如果模式被删除,则在第一个样本输入上$1~/.../
);但如果你知道那Name
始终是第一位的并且始终存在,那么一切都会变得容易得多:
awk '/^Name=/{printf "%s%s", nl, $0; nl=ORS}
/^(Class|School)=/{printf ", %s", $0}
END{if(nl) printf ORS}' /tmp/file.txt